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;
}