(Kruskal算法)Constructing Roads(12.1.1)

 

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

 

本人理解其实就是结合并查集的图的应用

#include<iostream>
#include <algorithm>
using namespace std;

int fa[120];
int get_father(int x)
{
	
	if(fa[x]==x)
		return x;
	else
		return  fa[x]=get_father(fa[x]);
	//	return fa[x]=fa[x]==x ?x:get_father(fa[x]);//判断两个节点是否属于一颗子树(并查集)
}
int main()
{
	int temp[15000],tem=0;
	int n;
	int p[120][120];
	while(scanf("%d",&n)!=EOF)
	{
		tem=0;
		int i,j,k,m;
		for(i=0;i<n;i++)
			for(j=0;j<n;j++)
			{
				scanf("%d",&p[i][j]);
			    temp[ p[i][j] ]=1;        //记录下在两个相邻的长度中有这个值
				                           //其实这个步骤可以没有,并且正宗的Kruskal算法好像也没有这个约束条
				                           // 设这个变量就是为了在后面遍历查找的时候会快一点,
				                          //但是事实表明,没有快,可能是后台的测试数据太少了。。。
			}
		for(i=0;i<n;i++)
			fa[i]=i;
			scanf("%d",&m);
		while(m--)
			{
				int a,b;
				scanf("%d%d",&a,&b);
				fa[get_father(a-1)]=get_father(b-1);// a  合并到 b
			}
		int ans=0;
		<span style="color:#ff0000;">for(k=0;k<=1000;k++)// kruskal 算法
		{
			if(temp[k]==1)//如果这个长度在路径中存在,如果直接没有当前距离的话就没有必要查找了
			{
			for(i=0;i<n;i++)
				for(int j=0;j<n;j++)
					if(p[i][j]==k && get_father(i)!=get_father(j))//当出现当前距离并且i和j未连接时,合并两个集合
					{
						fa[fa[i]]=fa[j];               //合并两颗子树(并查集)
						ans+=k;
					}
			}
		}
</span>		printf("%d\n",ans);
	}
	return 0;
}



 

 

 

 

 

 

 

 

你可能感兴趣的:((Kruskal算法)Constructing Roads(12.1.1))