• (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
    ",ans);
    	}
    	return 0;
    }
    



     

  • 相关阅读:
    JVM垃圾回收器(三)
    JVM 运行时数据区(二)
    JVM 虚拟机&&类加载(一)
    带你看看Java的锁(三)-CountDownLatch和CyclicBarrier
    带你看看Java的锁(二)-Semaphore
    带你看看Java的锁(一)-ReentrantLock
    C# 判断文件格式的一些总结
    qt creator源码全方面分析(4-6)
    c/c++调用matlab的matOpen()出现异常
    qt creator源码全方面分析(4-5)
  • 原文地址:https://www.cnblogs.com/zswbky/p/5432090.html
Copyright © 2020-2023  润新知