并查集 poj1703 Find them, Catch them

题目描述:
有两个犯罪团伙,有n个人,给m次信息,这m次信息会告诉你两种形式
1、“D” 表示告诉你两个人 x,y不是一个团伙的
2、“A”询问你x,y是否是一个团伙的,你有三种回答形式:“Not sure yet.”
“In different gangs.” “In the same gang.”

这题就是不管是不是一个团伙的,他们之间都有联系,相同团伙的在一个集合,不同团伙的是有另一种联系,这样的关系还是要表达出来的。接下来是具体思路

思路:这题最开始就能想到是并查集一类的题目,但是不同的是它给出的x,y不是一个集合的。由题目得这是两个犯罪团伙,那我可以设置两个集合,第一个集合是1到n,第二个集合是n+1到2*n。举个例子,D 1,2 和D 2,3,可知1,3是一个团伙的,2是另一个团伙的。对应前面的所说的,1,2,3在团伙一中表示的数字就是1,2,3,在团伙二中表示的数字是4,5,6.
那么他们之间的联系是什么。若1,3在团伙一中,那么2一定在团伙二中,而在团伙二中2所对应的数字就是5,团伙二中表示1,3的是4,6,他们非同一帮派,那么2和1,3的联系就可以通过1,5,3联系起来,同理,4,2,6也可以联系起来。
判断方式就是:在1到n的团伙一中,如果两个数字x,y都是小于等于n的,就是一团伙,如果一个是小于n,一个大于n,那么他们的关系就是非一团伙,可以由
x和y+n判断。

用模板来判断的话就是这样啦
if ( find(x)==find(y) ) 同一团伙
else if ( find(x)==find(y+n) ) 非同一团伙
else 那就not sure了。

这题的关键就是,每个数字还是要相互联系在一起的,只是一种联系方式是同一集合的联系,一种联系方式是非同一集合的联系。同一集合有关联的数字都是在同一个范围内的。

这题做完,请去做一题与这个思想一毛一样的题 poj2492 A Bug’s Life
当然还有进阶的,变成了三集合 POJ-1182 食物链

接下来就贴代码了


#include<cstdio>
#include<iostream>
using namespace std;

const int MAX=1e5*2+10;
int s[MAX];

int find(int x) {
	return x==s[x]?x:s[x]=find(s[x]);
}

void Union(int x, int y) {
	int fx=find(x);
	int fy=find(y);
	if ( x!=y ) s[fx]=fy;
}

int main()
{
	int t,n,m;
	char str[2];
	scanf("%d",&t);
	while(t--) {
		scanf("%d%d",&n,&m);
		for(int i=1; i<=n*2; i++ ) s[i]=i;
		int x,y;
		while(m--) {
			scanf("%s%d%d",str,&x,&y);
			if ( str[0]=='D' ) {
			//这里就是思路的内容啦,把两块相反的数字存到相反的集合里去
			//而相反的集合就是多开一组n就行了
				Union(x,y+n);        
				Union(x+n,y);
			}
			else if ( str[0]=='A' ) {
				if ( s[find(x)]==s[find(y)] ) printf("In the same gang.\n");
				else if ( s[find(x+n)]==s[find(y)] ) printf("In different gangs.\n");
				else printf("Not sure yet.\n");
			}
		}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章