POJ1703 Find them,Catch them

Description

题目大意:有两个帮派,龙帮派和蛇帮派,判断两个人a和b是不是同属于一个帮派

Input

第一行T表示有T组数据
每组数据第一行为n和m,代表n个人,m次查询
每次查询分别为
A a b 意思是:查询a和b是否在一个集合
D a b 意思是:a和b不在一个集合

Output

对于每个A查询,都输出三个答案,“In the same gang.”, “In different gangs.” and “Not sure yet.”

解题思路

记住一句话,敌人的敌人就是朋友,我们把每次D操作用foe数组记录为a和b互相为敌人,同时分别与对方的敌人合并,这样就不会两个人在一个集合,对于A查询操作,如果一个人和对方的敌人在一个集合,说明他们也是敌人,所以在不同的帮派,如果两个人在同一个集合说明他们在一个帮派,除此之外便是不确定,注意:cin输入会超时

代码

//freopen("hao.txt","r",stdin);
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 100005;
int foe[N];
struct Subset
{
	int parent;
	int rank;
}subsets[N];

int find(int x)
{
	if(subsets[x].parent!=x)
		subsets[x].parent = find(subsets[x].parent);

	return subsets[x].parent;
}

void Union(int x,int y)
{
	int x_root = find(x);
	int y_root = find(y);

	if(x_root==y_root)
		return;

	if(subsets[x_root].rank < subsets[y_root].rank){
		subsets[x_root].parent = y_root;
	}
	else if(subsets[x_root].rank > subsets[y_root].rank)
		subsets[y_root].parent = x_root;
	else {
		subsets[x_root].parent = y_root;
		subsets[y_root].rank++;
	}
}

int main()
{
	int T = 0;
	int n = 0,m = 0;
	char R;
	int people_a = 0,people_b = 0;

	freopen("hao.txt","r",stdin);
	scanf("%d",&T);

	while(T--)
	{

		cin>>n>>m;
		// 标记敌人
		memset(foe,0,sizeof(foe));

		for(int i=0;i<=n;i++) {
			subsets[i].rank = 0;
			subsets[i].parent = i;
		}
		for(int i=1;i<=m;i++)
		{
			scanf(" %c%d%d",&R,&people_a,&people_b);
			//cin>>R>>people_a>>people_b;
			if(R == 'A') {
				// 如果和a的敌人在一个集合,说明a和b在不同的帮派
				if(find(people_a) == find(foe[people_b]))
					printf("In different gangs.\n");
				// 如果两个人在一个集合,说明是相同的帮派
				else if(find(people_a)==find(people_b))
					printf("In the same gang.\n");
				else
					printf("Not sure yet.\n");
			}
			else {
				if(foe[people_a])
					Union(foe[people_a],people_b);
				if(foe[people_b])
					Union(foe[people_b],people_a);
				foe[people_a] = people_b;
				foe[people_b] = people_a;
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值