好久没写题解了……
题目描述:有N(1≤N≤2000)个节点,M(1≤M≤10000)条边。你要保留一些边,使得这个图连通且最大的边最小,输出最大边。
解题思路:→_→将边按权值从大到小排序,枚举从头开始删的边数~每次判一遍是否联通,感觉这样很对的说~
,→_→理想中的最坏情况时间复杂度会到达O(NM)即遍历删几条边的复杂度*bfs复杂度,啊咧不会超啊→_→,不过我用的是更快的方法↓
解题思路2:二分答案+bfs,每次二分bfs判断图的联通性,于是时间复杂度就变成了 二分的复杂度*bfs的复杂度 ,所以总的复杂度是O(log(max(边权))M)。↓ 代码略丑
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
int n,m;
bool b[2000+10];
int f[2001][2001][2];
#define max(a,b) (a>b?a:b)
inline int read(){
char ch;int a=0;bool f=false;
ch=getchar();while((ch<'0'||ch>'9')&&(ch!='-'))ch=getchar();
if(ch!='-')a*=10,a+=ch-'0';else f=true;
while(((ch=getchar())>='0')&&(ch<='9'))a*=10,a+=ch-'0';
if(f)a=-a;
return a;
}
bool find(int mid){
queue<int>Q;
int k=1;
memset(b,0,sizeof(b));
Q.push(1);b[1]=1;
while(!Q.empty()){
int x=Q.front();
for(int i=1;i<=f[x][0][0];i++){
if((!b[f[x][i][0]])&&(f[x][i][1]<=mid))
b[f[x][i][0]]=1,Q.push(f[x][i][0]),k++;
}
Q.pop();
if(k==n)return 1;
}
return 0;
}
int main(){
n=read(),m=read();
int Max=0;
for(int i=1;i<=m;i++){
int x,y,z;
x=read(),y=read(),z=read();
f[x][++f[x][0][0]][0]=y;
f[x][f[x][0][0]][1]=z;
f[y][++f[y][0][0]][0]=x;
f[y][f[y][0][0]][1]=z;
Max=max(z,Max);
}
int l=0,r=Max;
while(l<r){
int mid=(l+r)/2;
if(find(mid))r=mid;
else l=mid+1;
}
printf("%d",l);
}
loading...
评论 (0)