问题链接: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 ", ans[y]); return false; } else { v[x] = y; ans[y] += ans[x]; printf("%d ", 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 */