【POJ-1703】Find them, Catch them (并查集)

The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon and Gang Snake. However, the police first needs to identify which gang a criminal belongs to. The present question is, given two criminals; do they belong to a same clan? You must give your judgment based on incomplete information. (Since the gangsters are always acting secretly.) 

Assume N (N <= 10^5) criminals are currently in Tadu City, numbered from 1 to N. And of course, at least one of them belongs to Gang Dragon, and the same for Gang Snake. You will be given M (M <= 10^5) messages in sequence, which are in the following two kinds: 

1. D [a] [b] 
where [a] and [b] are the numbers of two criminals, and they belong to different gangs. 

2. A [a] [b] 
where [a] and [b] are the numbers of two criminals. This requires you to decide whether a and b belong to a same gang. 

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case begins with a line with two integers N and M, followed by M lines each containing one message as described above.

Output

For each message "A [a] [b]" in each case, your program should give the judgment based on the information got before. The answers might be one of "In the same gang.", "In different gangs." and "Not sure yet."

Sample Input

1
5 5
A 1 2
D 1 2
A 1 2
D 2 4
A 1 4

Sample Output

Not sure yet.
In different gangs.
In the same gang.

题意:

一个城市有两个集团,D [a] [b]表示a,b不在一个集团,A [a] [b]表示查询a,b在不在一个集团,根据已知做出三种回答。

解题报告:

带权并查集的题目,用一个数组w记录这个点与父节点的关系,所有已知关系的点都在一个集合中,有一个共同的根节点。如果根节点不同,表明这两个点关系未知。如果两个点与根节点的关系相同,则表明这两个点在同一个集团。否则在不同的集团。

注意:

这道题我一开始wa了几次,最后发现是因为输出的时候少了个句号。这样的错误根本不会提示格式错误,只会错。一定要注意这些小细节,要不根本找不出错误。

看了网上大佬的代码后,发现这么一种写法:scanf("%c%d%d%*c",&ch,&a,&b);这里的*c是用来吞掉回车的。

以下为网上查阅的:

格式字符串的一般形式为:
%[*][输入数据宽度][长度]类型
其中有方括号[]的项为任选项
“*”符:用以表示该输入项,读入后不赋予相应的变量,即跳过该输入值。

ac代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring> 
#include<queue>
#include<stack> 
#include<string.h>
#include<set>
using namespace std;
int n,t,m;
int f[100005];
int w[100005];//0同伙,1非同伙 ,关系数组 
void init()
{
	for(int i=0;i<=n+5;i++)
	{
		f[i]=i;
		w[i]=0; 
	}
}
int getf(int v)
{
	int temp=f[v];//一定要有,这是根据该点与原来父节点的关系来判断与根节点的关系
	if(f[v]!=v)
	f[v]=getf(f[v]);
	w[v]=(w[v]+w[temp])%2;//如果不用temp,而是用f[v]这是用该点和根节点的关系来求,这样是不对的
	return f[v];
}
void merge(int u,int v)
{
	int t1=getf(u);
	int t2=getf(v);
	if(t2!=t1)
	{
		f[t2]=t1;
		w[t2]=(w[u]+w[v]+1)%2;
	}
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		getchar();
		init();
		for(int i=1;i<=m;i++)
		{
			char op;
			int t1,t2;
			scanf("%c %d %d",&op,&t1,&t2);
			getchar();
			if(op=='D')
			{
				merge(t1,t2);
			}
			else if(op=='A')
			{
				int fa=getf(t1),fb=getf(t2);
				if(fa!=fb)
				{
					printf("Not sure yet.\n");
				}
				else
				{
					if((w[t1]+w[t2])%2==0)
					{
						printf("In the same gang.\n");
					}
					else
					{
						printf("In different gangs.\n");
					}
				}
			}
			
		}
	}	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/QQ_774682/article/details/81126299