BIT1062 Find them, Catch them

题意:

在一个城市里有两个犯罪团伙,现有N个犯罪事件,你知道M条信息

输入:

第一行是一个整数,代表样例的数目

每个样例的第一行是N和M

接下啦M行,每行有以下两种可能的形式

第一种:

D a B

意思是事件A和事件B是两个不同的犯罪团伙做的

第二种

A a b

问a和b是不是同一犯罪团伙干的

解法:

并查集,做了食物链之后做这题觉得好轻松。。。

分析:

定义并查集结构parent[],relation[]

parent[i]表示i的父节点的编号

relation[i]表示其与父节点的关系

为0表示与父节点是同一犯罪团伙

为1表示与父节点是不同犯罪团伙

设在并查集中a和b的根节点分别为ra和rb

设a到ra的带权距离为la

b到rb的带权距离为lb

a到b的带权距离为lab

则a到rb的带权距离为a->b->rb即lab+lb

BIT1062 Find them, Catch them_第1张图片

则有如图所示的结果

接下来上代码


#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int parent[100100];
int relation[100100];
struct T
{
	int num;//根节点的编号
	int quan;//到达根节点的带权距离
};
T root(int i)
{
	T ans;
	if(parent[i]==i)
	{
		ans.num=i;
		ans.quan=0;
		return ans;
	}
	T tt=root(parent[i]);
	parent[i]=tt.num;
	relation[i]+=tt.quan;
	relation[i]%=2;
	ans.num=parent[i];
	ans.quan=relation[i];
	return ans;
}
void Merge(int lab,int a,int b)//a和b不在同一伙
{
	T tempa=root(a);
	T tempb=root(b);
	int ra=tempa.num;
	int rb=tempb.num;
	int la=tempa.quan;
	int lb=tempb.quan;
	parent[ra]=rb;
	relation[ra]=(lab+lb-la)%2;
}
int main()
{
	int total;
	scanf("%d",&total);
	while(total--)
	{
		int n,m;
		scanf("%d %d",&n,&m);
		for(int i=1;i<=n;i++)
		{
			parent[i]=i;
			relation[i]=0;//为0代表和自己是同一犯罪团伙的
		}
		while(m--)
		{
			char type;
			int a,b;
			cin>>type;
			scanf("%d %d",&a,&b);
			if(type=='A')
			{
				T tempa=root(a);
				T tempb=root(b);
				int ra=tempa.num;
				int rb=tempb.num;
				if(ra!=rb)
				{
					printf("Not sure yet.\n");
				}
				else
				{
					if(tempa.quan==tempb.quan)
					{
						printf("In the same gang.\n");
					}
					else
					{
						printf("In different gangs.\n");
					}
				}
			}
			if(type=='D')
			{
				Merge(1,a,b);
			}
		}
	}
	return 0;
}






你可能感兴趣的:(BIT1062 Find them, Catch them)