#luogu整理 P1111 修复公路
并查集的题
luogu P1111 修复公路
思路
大体题意:给定n个点,一条一条边加到图里面,然后判断什么时候成为一个连通图。我一开始的时候是每增加一条边就重新扫一扫这个图,但是时间复杂度很显然不够用,所以我第一遍就炸了。后来我发现实际上每次加入一条边的时候,判断会不会减少一个连通块就可以。
注意事项:
并查集容易出现的bug:每次合并的时候,代码应该写成这样:
fa[getfa(x)] = getfa(y); 或者
fa[getfa(x)] = y;
因为x的fa可能会链接这其他的点,如果直接更改x的fa,课能会导致他原有的父亲“丢失”。
代码
注释里面的是我第一遍的文件。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct EDGE{
int x,y,num;
}edge[100009];
bool cmp(EDGE a,EDGE b){
return a.num < b.num;
}
int fa[100009];
int getfa(int x){
return x == fa[x] ? x : getfa(fa[x]);
}
int n,m;
int main(){
cin >> n >> m;
for(int i = 1;i <= m; i++){
cin >> edge[i].x >> edge[i].y >> edge[i].num;
}
n--;
sort(edge+1,edge+1+m,cmp);
for(int i = 1;i <= n; i++){
fa[i] = i;
}
//cout << endl;
// for(int i = 1;i <= m; i++){
// //cout << edge[i].x << ' ' << edge[i].y << ' ' << edge[i].num << endl;
// }
// int i = 0;
// while(i <= m){
// i++;
// int x = edge[i].x,y = edge[i].y;
// while(edge[i].num == edge[i+1].num){
// fa[getfa(x)] = getfa(y);
// //cout << i << endl;
// i++;
// }
// x = edge[i].x,y = edge[i].y;
// fa[getfa(x)] = getfa(y);
// bool fd = 0;
// for(int j = 1;j <= n; j++){
// //cout << fa[j] << ':';
// }
// //cout << endl;
// for(int j = 1;j <= n; j++){
// if(getfa(j) != getfa(n)) fd = 1;
// }
// if(!fd){ cout << edge[i].num << endl; return 0;}
// }
for(int i = 1;i <= m; i++){
// cout << edge[i].x << ' ' << edge[i].y << ' ' << edge[i].num << endl;
int x = getfa(edge[i].x),y = getfa(edge[i].y);
if(x != y){fa[x] = y;n--;}
// cout << x << ':' << y << endl;
if(n <= 0){cout << edge[i].num << endl;return 0;}
}
cout << -1 << endl;
return 0;
}