杭电 hdu 1102 Constructing Roads (最小生成树)

杭电  hdu   1102  Constructing Roads  (最小生成树)


Constructing Roads

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 16548    Accepted Submission(s): 6297


Problem Description
There are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We say two village A and B are connected, if and only if there is a road between A and B, or there exists a village C such that there is a road between A and C, and C and B are connected. 

We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum.
 

Input
The first line is an integer N (3 <= N <= 100), which is the number of villages. Then come N lines, the i-th of which contains N integers, and the j-th of these N integers is the distance (the distance should be an integer within [1, 1000]) between village i and village j.

Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built.
 

Output
You should output a line contains an integer, which is the length of all the roads to be built such that all the villages are connected, and this value is minimum. 
 

Sample Input

3 0 990 692 990 0 179 692 179 0 1 1 2
 

Sample Output

179
 

Source
kicc
 

Recommend
Eddy   |   We have carefully selected several similar problems for you:   1301  1162  1879  1863  1217 
 







题意:有n个村庄,要将所有的村庄连接起来,而这些村庄原先就有一些村庄是相互通的,然后告诉你所有的村庄相互之间的距离,问你还要
修多少长的距离能让所有村庄连接起来
首先输入n,表示有多少个村庄,
然后是n*n的矩阵,表示每个村庄之间的距离
然后是m,表示本来存在多少的路
然后a,b表示a村庄到b村庄连通






题解:通过最小生成树,先将已经连通的村庄连接起来,然后再从矩阵中找边,找短的,并且合适的边,组成完整的最小生成树
其实就是通过并查集,查找祖先结点不同的,就连接起来。





#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 10005;

struct node{                    //用来存放边,从from到to,还有相隔的距离
	int a;
	int b;
	int v;
}tree[maxn];

bool cmp(node a, node b){             //优先级,使结构体中距离短的放在前面
	return (a.v < b.v);
}

int father[maxn];
int sum;

void Init (){
	int i;

	for (i = 1; i < maxn; ++i)             //让刚开始的父亲结点设为自己
		father[i] = i;
}

int Find (int x){                            //寻找祖先结点
	int rt = x;

	if (father[x] != x){
		rt = Find (father[x]);
		father[x] = rt;
	}
	return rt;
}

bool Union(int a, int b){
	int fa = Find (a);
	int fb = Find (b);

	if (fa != fb){                               //如果祖先结点不同,那边表明没有环,可以连接
		father[fa] = fb;
		return true;
	}
	return false;
}

int main (){
	int T, n, a, b, i, j;

	while (scanf ("%d", &T) != EOF){
		int num = 0;
		sum = 0;
		Init ();
		for (i = 1; i <= T; ++i)
			for (j = 1; j <= T; ++j){
				scanf ("%d", &tree[num].v);                 //将边存储到tree[]结构体中
				tree[num].a = i;
				tree[num++].b = j;
			}
		sort (tree, tree + (T * T), cmp);                  //优先级排序
		scanf ("%d", &n);
		for (i = 1; i <= n; ++i){                       //构造树
			scanf ("%d%d", &a, &b);
			Union(a, b);
		}
		for (i = 0; i < T * T; ++i){
			if (Union (tree[i].a, tree[i].b)){
				sum += tree[i].v;                               //记录总共要修的距离
			} 
		}
		printf ("%d\n", sum);
	}
}


你可能感兴趣的:(并查集,最小生成树)