题目链接:https://ac.nowcoder.com/acm/contest/12794/F
并查集添边时若该边重复添加,则证明该连通分量中有闭环,注意这点的维护!!!
#include<iostream>
#include<algorithm>
#include<cstring>
#include <vector>
#include<stack>
using namespace std;
const int maxn = 500000 + 5;
int m,n;
int pre[maxn];
bool cir[maxn] = {0};
int vis[maxn] = {0};
int _fix = 0, ans = 0;
int Find(int a) {
if(pre[a] != a) pre[a] = Find(pre[a]);
return pre[a];
}
void join(int a, int b) {
int _a = Find(a);
int _b = Find(b);
if(_a != _b) {
pre[_b] = _a;
vis[_a] += vis[_b];
if(cir[_a] && cir[_b]) {
_fix--;
}
if(cir[_b] && !cir[_a]) {
cir[_a] = 1;
}
}
else if(_a == _b && cir[_a] == 0) {
cir[_a] = 1;
_fix++;
}
}
void init() {
_fix = 0; ans = 0;
for(int i = 1; i <= n; ++i) {
pre[i] = i;
vis[i] = 1;
cir[i] = 0;
}
}
int main() {
int kk;
cin >> kk;
for(int k = 1; k <= kk; ++k) {
cin >> n >> m;
init();
for(int i = 1; i <= m; ++i) {
int u,v;
cin >> u >> v;
join(u,v);
}
int t;
for(int i = 1; i <= n; ++i) {
if(pre[i] == i && vis[i] > 1) {
++ans;
}
}
cout <<"Night sky #" << k <<": " <<ans << " constellations, of which " << _fix <<" need to be fixed. "<< endl<<endl;
}
return 0;
}