Hdu3371【最小生成树】

/*Connect the Cities 
Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 0   Accepted Submission(s) : 0
Font: Times New Roman | Verdana | Georgia 
Font Size: ← →
Problem Description
In 2100, since the sea level rise, most of the cities disappear. Though some survived cities are still connected with others, but most 
of them become disconnected. The government wants to build some roads to connect all of these cities again, but they don’t want to take too
 much money.   
Input
The first line contains the number of test cases.
Each test case starts with three integers: n, m and k. n (3 <= n <=500) stands for the number of survived cities, m (0 <= m <= 25000) stands
 for the number of roads you can choose to connect the cities and k (0 <= k <= 100) stands for the number of still connected cities.
To make it easy, the cities are signed from 1 to n.
Then follow m lines, each contains three integers p, q and c (0 <= c <= 1000), means it takes c to connect p and q.
Then follow k lines, each line starts with an integer t (2 <= t <= n) stands for the number of this connected cities. Then t integers follow 
stands for the id of these cities.

Output
For each case, output the least money you need to take, if it’s impossible, just output -1. 
Sample Input
1
6 4 3
1 4 2
2 6 1
2 3 5
3 4 33
2 1 2
2 1 3
3 4 5 6

Sample Output
1
Author
dandelion */ 
#include<stdio.h>
#include<stdlib.h>
int map[510], a[510], b[510];
struct road
{
	int i, j, cost;
}r[25010];
int cmp(const void *a, const void *b)
{
	return (*(struct road*)a).cost - (*(struct road *)b).cost;
}
int find(int x)
{
	if(x != a[x])
	{
		a[x] = find(a[x]);
	}
	return a[x];
}
int merge(int x, int y)
{
	x = find(x);
	y = find(y);
	if(x != y)//集合不同 合并 
	{
		a[x] = y;
		return 1;
	}
	return 0;
}
int main() 
{
	int T;
	scanf("%d", &T);
	while(T--)
	{
		int n, m, k;
		scanf("%d%d%d", &n, &m, &k);
		for(int i = 1; i <= n; i++)
		a[i] = i;
		for(int i = 1; i <= m; i++)//保存桥   注意重边 (经过排序后可以忽略) 
		{
			scanf("%d%d%d", &r[i].i, &r[i].j, &r[i].cost);
		}
		for(int i = 0; i < k; i++)//k个已经相连的情况 
		{
			int x, y, t;
			scanf("%d", &t);
			scanf("%d", &x);
			x = find(x);
			while(--t)//将这t个数合并
			{
				scanf("%d", &y);
				y = find(y);
				if(x != y)
				{
					a[y] = x;
				} 
			}
		}
		qsort(r+1, m, sizeof(r[0]), cmp);
		int money = 0;
		for(int i = 1; i <= m; i++)
		{
			if( merge(r[i].i, r[i].j) && r[i].cost)
			{
				money += r[i].cost;
			}
		}
		int j = 0;
		for(int i = 1; i <= n; i++)//判断是否连通
		if(a[i] == i)
		j++;
		if(j > 1)
		printf("-1\n");
		else
		printf("%d\n", money);
	}
	return 0;
}
题意:由于海平面上升,许多城市已经消失了,政府想要在幸存的城市之间建路,输入n,m,k,n表示幸存的城市,接下来m行每行都有3个数字p q c ,表示连接p和q需要花费c,接着k行每行也有若干个数,第一个数t表示有几个城市依然是相通的,接下来会给出依旧相通的那t个城市的编号,每一行都是这种输入。现在求政府最少需要花费多少可将这n个城市连通。
思路:首先需要将k行的k个集合分别给合并出独立的集合,接着再对政府需要建设的路进行排序,选择花费最小的城市进行连通,若已经连通则跳过该条路,若这2个城市未连通则合并,直至所有的路都已遍历,最后查询所有的城市是否连通,若连通的话所有点的父节点会是同一个点,如果大于一个父节点说明未全部连通输出-1,否则输出最小的花费。

你可能感兴趣的:(c)