|Tyvj|并查集|P1602 团伙

http://tyvj.cn/p/1602

方法一:拆点

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define ms(i,j) memset(i,j, sizeof i);
using namespace std; 
int n,m; 
int father[2005];
int find(int x)
{
	if (father[x]==x) return x;
	return father[x] = find(father[x]);
}
int merge(int x, int y)
{
	int x1 = find(x);
	int y1 = find(y);
	if (x1!=y1) father[y1] = x1;
}
int main()
{
	scanf("%d%d", &n, &m);
	for (int i=1;i<=2*n;i++) father[i] = i;
	for (int i=1;i<=m;i++)
	{
		char ch[10];
		int p,q;
		scanf("%s %d %d", ch, &p, &q);
		char c = ch[0];
		if (c=='F')
		{
			merge(p,q);
		} else
		{
			merge(p, q+n);
			merge(q, p+n);
		}
	}
	int ans = 0;
	for (int i=1;i<=2*n;i++) find(i);
	for (int i=1;i<=n;i++)
	if (father[i]==i) ans++;
	printf("%d\n", ans);
    return 0;
}

方法二:输入如果是朋友就合并,是敌人就邻接表储存起来,然后输入完之后合并所有的敌人,最后统计代表个数即可

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int num[1005], f[1005][1005];
int father[1005];
int n,m;
int find(int i)
{
	if (father[i]!=i) father[i] = find(father[i]);
	return father[i];
}
int merge(int x, int y)
{
	int r1 = find(x);
	int r2 = find(y);
	father[r2] = r1;
}
int main () 
{ 
	scanf("%d%d%*c", &n, &m);
	for (int i=1;i<=n;i++) father[i] = i;
	memset(num, 0, sizeof(num));
	for (int i=1;i<=m;i++)
	{
		char c;
		int p,q;
		c = getchar();
		scanf("%d%d%*c", &p, &q);
		if (c=='F')
		{
			merge(p, q);
		} 
		else 
		{
			f[p][++num[p]] = q;
			f[q][++num[q]] = p;
		}
	}	
	for (int k=1;k<=n;k++)
	{
		for (int i=1;i<=num[k];i++)
		for (int j=1;j<=num[k];j++)
		{
			merge(f[k][i], f[k][j]);
		}
	}
	for (int i=1;i<=n;i++) find(i);
	int ans = 0;
	for (int i=1;i<=n;i++)
	{
		if (father[i]==i) ans++;
	}
	printf("%d\n", ans);
	return 0;
}

    原文作者:犯罪团伙问题
    原文地址: https://blog.csdn.net/Darost/article/details/52195972
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞