【HDU - 5631】Rikka with Graph


點擊打開鏈接


Rikka with Graph

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1233    Accepted Submission(s): 639


Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

Yuta has a non-direct graph with n vertices and n+1 edges. Rikka can choose some of the edges (at least one) and delete them from the graph.

Yuta wants to know the number of the ways to choose the edges in order to make the remaining graph connected.

It is too difficult for Rikka. Can you help her?
 

Input
The first line contains a number T(T30)——The number of the testcases.

For each testcase, the first line contains a number n(n100).

Then n+1 lines follow. Each line contains two numbers u,v , which means there is an edge between u and v.
 

Output
For each testcase, print a single number.
 

Sample Input
1 3 1 2 2 3 3 1 1 3
 

Sample Output
9
 

//代碼如下:

#include <stdio.h>
#include <string.h>

const int maxn = 1e2 + 10;

int par[maxn];

struct node   //把邊用結構體存下來,每個結構體對應一條邊; 
{
	int st;
	int edd;
}edge[maxn];

void init(int n)
{
	for (int i = 0; i <= n; i++)
		par[i] = i;
}

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

void unite(int a, int b)
{
	int fa = find(a);
	int fb = find(b);
	if (fa != fb)	
		par[fa] = fb;
}

bool check(int n)    //統計是不是隻有一個根節點,即使不是能全部連通 
{
	int sum = 0;
	for (int i = 1; i <= n; i++)
		if (par[i] == i)
			sum++;
	return sum == 1;
}

int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		int n;
		scanf("%d", &n);
		for (int i = 0; i < n + 1; i++)
			scanf("%d%d", &edge[i].st, &edge[i].edd);
		int sum = 0;   //sum記錄可行的個數
		//題上說總共給出n + 1條邊 然後我們已知n個點至少需要n - 1條邊連接   數據是100左右  n^3也可以過  那就暴力枚舉
		//先枚舉去掉一條邊是否能連通
		for (int i = 0; i < n + 1; i++)
		{
			init(n); //這一步記得 因爲是枚舉 每次枚舉出來一條邊 這個數組就要重新排列一下  回覆初始狀態 
			for (int j = 0; j < n + 1; j++)
			{
				if (i == j) //上面用i記錄去掉的邊 那麼這一步就沒有這條邊了 所以遇到相等就跳過 
					continue;
				unite(edge[j].st, edge[j].edd); //把剩下的每個邊都連接起來  
			}
			//然後在這做檢查 看能不能連通所有的點 
			if (check(n))
				sum++; 
		} 
		//枚舉一條邊的就結束了  下面的兩條邊的和一條邊的幾乎相同  
		for (int i = 0; i < n + 1; i++)
		{
			for (int j = i + 1; j < n + 1; j++)
			{
				init(n);
				for (int k = 0; k < n + 1; k++)
				{
					if (k == i || k == j)
						continue;
					unite(edge[k].st, edge[k].edd);
				}
				if (check(n))
					sum++;
			}
		}
		printf("%d\n", sum); 
	}
	return 0;
}










發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章