并查集部分汇总

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


猜你喜欢

转载自blog.csdn.net/usernamezzz/article/details/80227211