问题链接:HDU3172 UVA11503 Virtual Friends。
问题简述:一个计算朋友圈大小的问题,参见上述链接。
问题分析:这是一个有关图的连通性问题,可以用并查集来解决。并查集中,连通的各个结点都会指向相同的根。相互连通的子图,其结果之和存储在根结点中。
程序说明:程序中,构建一个用并查集,使得相互连通的子图指向相同的根。该程序与其他程序略有不同的地方是,并查集用数组来存储(可以用向量vector来存储的),目的是加快计算时间。另外由于该问题的测试用例多,输出结果多,需要用C语言的输入输出方式,才能够加快速度,以免超时。同样,输出也合并到并查集中,以提高计算速度。
AC的C++语言程序如下:
/* HDU3172 UVA11503 Virtual Friends */
#include <iostream>
#include <map>
#include <string>
using namespace std;
const int MAXN = 100000;
int v[MAXN+1];
int ans[MAXN+1];
// 并查集类
class UF {
private:
int length;
public:
UF(int n) {
length = n;
for(int i=0; i<=n; i++)
v[i] = i;
}
int Find(int x) {
for(;;) {
if(v[x] != x)
x = v[x];
else
return x;
}
}
bool Union(int x, int y) {
x = Find(x);
y = Find(y);
if(x == y) {
printf("%d\n", ans[y]);
return false;
} else {
v[x] = y;
ans[y] += ans[x];
printf("%d\n", ans[y]);
return true;
}
}
void reset() {
for(int i=0; i<=length; i++)
v[i] = i;
}
};
int main()
{
int t, f, no, pno1, pno2;
char name1[30], name2[30];
map<string, int> m;
UF uf(MAXN+1);
// while(cin >> t) {
while(scanf("%d", &t) != EOF) {
while(t--) {
// cin >> f;
scanf("%d", &f);
for(int i=0; i<=MAXN; i++)
ans[i] = 1;
m.clear();
uf.reset();
no = 0;
for(int i=1; i<=f; i++) {
// cin >> name1 >> name2;
scanf("%s%s", name1, name2);
// 将名字放入map中,并将名字映射为整数
if(!(pno1 = m[name1]))
m[name1] = (pno1 = ++no);
if(!(pno2 = m[name2]))
m[name2] = (pno2 = ++no);
// 合并,同时输出结果
uf.Union(pno1, pno2);
}
}
}
return 0;
}
/*
测试实例:
1
6
Fred Barney
Barney Betty
Betty Wilma
AAAAA BBBBB
AAAA BBBBB
AAAA Fred
输出:
2
3
4
2
3
7
*/