poj2492 A Bug's Life

先上題目:

4:A Bug's Life
查看提交統計提問
總時間限制: 10000ms 內存限制: 65536kB
描述
Background
Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different genders and that they only interact with bugs of the opposite gender. In his experiment, individual bugs and their interactions were easy to identify, because numbers were printed on their backs.
Problem
Given a list of bug interactions, decide whether the experiment supports his assumption of two genders with no homosexual bugs or if it contains some bug interactions that falsify it.
輸入
The first line of the input contains the number of scenarios. Each scenario starts with one line giving the number of bugs (at least one, and up to 2000) and the number of interactions (up to 1000000) separated by a single space. In the following lines, each interaction is given in the form of two distinct bug numbers separated by a single space. Bugs are numbered consecutively starting from one.
輸出
The output for every scenario is a line containing "Scenario #i:", where i is the number of the scenario starting at 1, followed by one line saying either "No suspicious bugs found!" if the experiment is consistent with his assumption about the bugs' sexual behavior, or "Suspicious bugs found!" if Professor Hopper's assumption is definitely wrong.
樣例輸入
2
3 3
1 2
2 3
1 3
4 2
1 2
3 4
樣例輸出
Scenario #1:
Suspicious bugs found!

Scenario #2:
No suspicious bugs found!
提示
Huge input,scanf is recommended.
來源
TUD Programming Contest 2005, Darmstadt, Germany

  1. 依然是並查集的應用之帶關係的並查集,是poj1182的簡化版本:不同於poj1182中兒子與父親結點之間存在三種關係(同類0、父吃子1、子吃父2),此題中兒子與父親結點之間只有兩種關係(同性0、異性1)。
  2. 初始狀態時所有的結點都在不同的樹中,所有結點的r[]值都爲0。如果題目給出的數據能cover所有結點,那麼最後的狀態必然是只有一棵樹,n-1個結點(兒子)指向同一個根(父親),它們的r[]值各異(依賴於與父親的關係。當然,是更新過的)。這一整棵樹的根結點就是最初合併的兩個結點之一
  3. 輸入的兩個結點先分別執行find,若在一棵樹中,以根結點爲參照判斷它們是否爲同性。
  4. 接3,若不在一棵樹中,則合併。合併時默認x與y是異性(異性“名額”先到先得),有(fy-->fx)=(fy-->y)+(y-->x)+(x-->fx),即r[fy]=(2-r[y] +1 + r[x])%2。
  5. 若仍有疑問,請看我對poj1182的詳細分析:poj1182 食物鏈,並查集,向量,可能是史上關於此題最清晰易懂的題解

代碼清單
#include <cstdio>

#define MAXN 2010

int p[MAXN];	//儲存結點的父親信息
int r[MAXN];	//儲存與父親結點的關係:0同性,1異性

void init(int n)
{
	int i;
	for (i=0; i<=n; ++i)
	{
		p[i]=i;	//初始時所有結點的父親是它自己
		r[i]=0;	//初始時所有結點與其父親(也就是它自己)同性
	}
}

int find(int x)
{
	if(x==p[x]) return x;	//路徑的最末端,父親就是它自己

	//否則遞歸查找
	int t=p[x];
	p[x]=find(p[x]);	//回溯時將所有結點都指向始祖
	r[x]=(r[x]+r[t])%2;	//回溯時更新與新的父結點(即始祖)的關係

	return p[x];
}

//1.union只在find(x)!=find(y)時候做
//2.union的時候默認x與y是異性---其實是一個構建過程,異性“名額”先到先得
//3.把fy嫁接到fx上,並更新關係
void Union(int x, int y)
{
	int fx=find(x);
	int fy=find(y);

	p[fy]=fx;
	r[fy]=(2-r[y] + 1 + r[x])%2;	//中間的1意味着默認x與y是異性
}

int main()
{
	//freopen("D:\\in.txt", "r", stdin);
	//freopen("D:\\out.txt", "w", stdout);

	int t, i, n, k, x, y, j, homo;

	scanf("%d", &t);

	for (i=0; i<t; ++i)
	{
		scanf("%d%d", &n, &k);

		init(n);	//初始化
		homo=0;

		for (j=0; j<k; ++j)
		{
			scanf("%d%d", &x, &y);
			if(find(x)==find(y))	//x,y已經在同一棵樹中,那麼判斷x,y是否爲同性
			{
				if( (r[x]+2-r[y])%2 == 0 )	//x和y是同性
					homo=1;
				else
					continue;	//是異性就繼續
			}
			else	//若x,y不在一棵樹中,默認它們是異性(所謂異性名額先到先得)
				Union(x, y);
		}

		printf("Scenario #%d:\n", i+1);
		if (homo)
			printf("Suspicious bugs found!\n\n");
		else
			printf("No suspicious bugs found!\n\n");
	}

	return 0;
}



發佈了50 篇原創文章 · 獲贊 16 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章