题意:给出一个连通图,但给出的某些边断掉了,求出需要最少修复几条边,能使整个图联通。
思路:相互可以到达的点形成一个连通块。断掉的边使整个图形成几个连通块。我们只需要在不同的连通块间连修复一条边就可以使整个图连通。
而图的连通性可以通过并查集维护。
并查集维护整个图有多少个连通块。连通块的个数减1就是答案。
代码如下:
#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
#include <utility>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
int N,M;
struct DisjointSet{
int ans;
vector<int> father,rank;
DisjointSet(int n):father(n+1),rank(n+1),ans(n){
for(int i = 1; i<= n; ++i)
father[i] = i;
}
int find(int x){
return x == father[x] ? x : x = find(father[x]);
}
void merge(int x,int y){
x = find(x);
y = find(y);
if(x != y){
ans--;
if(rank[x] > rank[y])
father[x] = y;
else{
father[y] = x;
if(rank[x] == rank[y])
rank[y]++;
}
}
return;
}
};
int main(void)
{
while(scanf("%d %d",&N,&M) != EOF){
DisjointSet s(N);
for(int i = 0 ; i < M; ++i){
int from,to,cost;
scanf("%d %d %d",&from,&to,&cost);
if(cost == 0)
s.merge(from,to);
}
printf("%d\n",s.ans-1);
}
return 0;
}