利用并查集做
设某个要计算的点为p
然后对与p连接的那些点做深度搜索,然后在dfs中对他们经行合并操作。
最后判断祖先的数量有多少,若>1,则有几个祖先就说明有几个不一样的子集,也就是不能互相访问的子网。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<vector>
#include<set>
#include<queue>
#include<list>
using namespace std;
vector<int> map[1001];
int anc[1001];
int maxn = 0;
int vis[1001];
int val[1001];
int temp[1001];
void init() {
for (int i = 0; i <= maxn; i++) {
map[i].clear();
}
maxn = 0;
}
int Find(int id) {
return (anc[id] == id) ? id : (anc[id] = Find(anc[id]));
}
void unio(int p1, int p2) {
int fp1 = Find(p1);
int fp2 = Find(p2);
if (val[fp1] > val[fp2]) {
anc[p2] = fp1;
val[fp1] += val[fp2];
} else {
anc[p1] = fp2;
val[fp2] += val[fp1];
}
}
void dfs(int id) {
vector<int> nd = map[id];
for (int i = 0; i < nd.size(); i++) {
if (!vis[nd[i]]) {
vis[nd[i]] = 1;
unio(id, nd[i]);
dfs(nd[i]);
}
}
}
int main() {
int u, v, cur;
cur = 0;
while (cin >> u) {
if (!u) break;
if(cur){
cout << endl;
}
cin >> v;
init();
map[u].push_back(v);
map[v].push_back(u);
maxn = max(maxn, max(u, v));
while (cin >> u) {
if (!u) break;
cin >> v;
map[u].push_back(v);
map[v].push_back(u);
maxn = max(maxn, max(u, v));
}
printf("Network #%d\n", ++cur);
int flag=0;
for (int i = 1; i <= maxn; i++) {
vector<int> roots = map[i];
memset(vis, 0, sizeof(vis));
memset(temp, 0, sizeof(temp));
//初始化
for (int i = 1; i <= maxn; i++) {
anc[i] = i;
val[i] = 1;
}
vis[i] = 1;
for (int j = 0; j < roots.size(); j++) {
if (vis[roots[j]])continue;
vis[roots[j]] = 1;
dfs(roots[j]);
}
int res = 0;
for (int j = 0; j < roots.size(); j++) {
int fa = Find(roots[j]);
if (!temp[fa]) {
res++;
temp[fa] = 1;
}
}
// printf("forbid i:%d\n", i);
// for (int j = 1; j <= maxn; j++) {
// cout << j << "anc:" << anc[j] << endl;
// }
if (res > 1) {
printf(" SPF node %d leaves %d subnets\n", i, res);
flag=1;
}
}
if(!flag){
cout << " No SPF nodes"<<endl;
}
}
}