並查集 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章