POJ-1988
题意:有n个箱子,初始时每个箱子单独为一列;
接下来有p行输入,M, x, y 或者 C, x;
对于M,x,y:表示将x箱子所在的一列箱子搬到y所在的一列箱子上;
对于C,x:表示求箱子x下面有多少个箱子;
定义d数组表示x下面有多少箱子
定义s数组表示当前集合有多少箱子
fa[x]=y;x的父亲节点为y;
#include<iostream> #include<algorithm> #include<cstdio> #define maxn 30007 int s[maxn]; int fa[maxn], d[maxn]; int Find(int x) { if (fa[x] != x) { int t = fa[x]; fa[x] = Find(fa[x]); d[x] = d[x] + d[t]; } return fa[x]; } void insert(int x, int y) { x = Find(x); y = Find(y); if (x != y) { fa[x] = y; d[x] += s[y]; s[y] += s[x]; s[x] = 0; } } int main() { int t; int x, y; char enter, temp; for (int i = 1; i <= maxn; i++) { s[i] = 1; d[i] = 0; fa[i] = i; } scanf("%d%c", &t,&enter); while (t--) { scanf("%c", &temp); if (temp == 'M') { scanf("%d%d%c", &x, &y, &enter); insert(x, y); } else { scanf("%d%c", &x, &enter); Find(x); printf("%d\n", d[x]); } } return 0; }
POJ-2236
并查集,提高题。
算是并查集的应用,拐了点弯。
题意:
有一个计算机网络的所有线路都坏了,网络中有n台计算机,现在你可以做两种操作,修理(O)和检测两台计算机是否连通(S),只有修理好的计算机才能连通。连通有个规则,两台计算机的距离不能超过给定的最大距离D(一开始会给你n台计算机的坐标)。检测的时候输出两台计算机是否能连通。
思路:
每次修理好一台计算机的时候就遍历一下所有修好的计算机,看距离是否<=D,如果符合说明可以连通,将两台计算机所在集合合并。
每次检查的时候判断一下这两台计算机是否在同一集合中即可。
#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> using namespace std; int v[1005]; int n, m; struct p { int x; int y; int f; }point[1005]; int Find(int x) { if (point[x].f != x) { point[x].f = Find(point[x].f); } return point[x].f; } void z_set(int p) { int i; for (i = 1; i <= n; i++) { if (i != p && v[i]==1) { if (abs(point[p].x - point[i].x)*abs(point[p].x - point[i].x) + abs(point[p].y - point[i].y)*abs(point[p].y - point[i].y) <= m * m) { int xx = Find(p); int yy = Find(i); if (xx != yy) point[yy].f = xx; } } } } void M_set(int x, int y) { int xx = Find(x); int yy = Find(y); if (xx != yy) { cout << "FAIL" << endl; } else cout << "SUCCESS" << endl; } int main() { int p,nn; int x1, y1; char temp, enter; int k; scanf("%d%d", &n, &m); k = 1; nn = n; for (int i = 1; i <= n; i++) point[i].f = i; memset(v, 0, sizeof(v)); while (nn--) { scanf("%d%d", &x1, &y1); point[k].x = x1; point[k++].y = y1; } while (cin>>temp) { if (temp == 'O') { scanf("%d", &p); v[p] = 1; z_set(p); } else { scanf("%d%d", &x1, &y1); if (v[x1] == 0 || v[y1] == 0) cout << "FAIL" << endl; else { M_set(x1, y1); } } } return 0; }
POJ-2492
题意:调查一种虫子的性行为,先假定虫子里没有同性恋。每一次测试输入N只虫,然后输入M个数对( x, y ),表示 x, y 之间有性行为, 最后判断假设成立与否(即判断有没有同性恋)。
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; int p[2010], r[2010]; int Find(int x) { if (x != p[x]) { int t = p[x]; p[x] = Find(p[x]); r[x] = (r[x] + r[t]) % 2; } return p[x]; } int main() { int t,k=1; int n, m; int flag; int x, y; scanf("%d", &t); while (t--) { flag = 1; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { p[i] = i; r[i] = 0; } for (int i = 0; i < m; i++) { if (flag) { scanf("%d%d", &x, &y); int xx = Find(x); int yy = Find(y); if (xx == yy) { if (r[x] == r[y]) { flag = 0; } } else { if (xx < yy) { p[yy] = xx; r[yy] = (r[x] - r[y] + 1) % 2; } else { p[xx] = yy; r[xx] = (r[x] - r[y] + 1) % 2; } } } else scanf("%d%d", &x, &y); } cout << "Scenario #" << k++ << ":" << endl; if (flag) cout << "No suspicious bugs found!\n\n"; else cout << "Suspicious bugs found!\n\n"; } return 0; }