最小生成树

问题 E: 算法7-9:最小生成树

 

题目描述

最小生成树问题是实际生产生活中十分重要的一类问题。假设需要在n个城市之间建立通信联络网,则连通n个城市只需要n-1条线路。这时,自然需要考虑这样一个问题,即如何在最节省经费的前提下建立这个通信网。

可以用连通网来表示n个城市以及n个城市之间可能设置的通信线路,其中网的顶点表示城市,边表示两个城市之间的线路,赋于边的权值表示相应的代价。对于n个顶点的连通网可以建立许多不同的生成树,每一棵生成树都可以是一个通信网。现在,需要选择一棵生成树,使总的耗费最小。这个问题就是构造连通网的最小代价生成树,简称最小生成树。一棵生成树的代价就是树上各边的代价之和。

而在常用的最小生成树构造算法中,普里姆(Prim)算法是一种非常常用的算法。

在本题中,读入一个无向图的邻接矩阵(即数组表示),建立无向图并按照以上描述中的算法建立最小生成树,并输出最小生成树的代价。

 

 

输入

输入的第一行包含一个正整数n,表示图中共有n个顶点。其中n不超过50。

以后的n行中每行有n个用空格隔开的整数,对于第i行的第j个整数,如果不为0,则表示第i个顶点和第j个顶点有直接连接且代价为相应的值,0表示没有直接连接。当i和j相等的时候,保证对应的整数为0。

输入保证邻接矩阵为对称矩阵,即输入的图一定是无向图,且保证图中只有一个连通分量。

 

输出

只有一个整数,即最小生成树的总代价。请注意行尾输出换行。

 

样例输入

4
0 2 4 0
2 0 3 5
4 3 0 1
0 5 1 0

 

样例输出

6

 AC代码

#include
#include
int main()
{
    int n,i,j,min=9999,u,sum=0,t=1;
    int a[55][55],x[55],d[55],s[55];
    scanf("%d",&n);
    
    for(i=0;i     for(j=0;j     scanf("%d",&a[i][j]);
    memset(x,0,sizeof(x));       //记录已经走过的点
    memset(d,0,sizeof(d));       //记录从这一点到各个点的路程
    memset(s,0,sizeof(s));       //记录到达该点的最短路程
    
    for(i=0;i     {
        if(a[0][i]!=0)
        d[i]=a[0][i];
        else
        d[i]=999999;              //  重点,必须要赋予一个最大值,以方便后面工作的进行,或者将整体的0全部赋予最大值
    }
    
    x[0]=1;
    s[0]=0;                         //因为在这里已经路过第一个点,所以s的初始值为1
    
    while(t     {
        min=999999;
        for(i=0;i         {
            if(d[i]             {
                min=d[i];j=i;
            }
        }
        
        s[j]=min;x[j]=1;
       
        for(i=0;i         {
            if(x[i]==0&&d[i]>a[j][i]&&a[j][i]!=0)          /*a[j][i]!=0,如果将所有0值全部替换掉,就可以不用这个条件,这个条件是为了防止因为0的出现而导致有效被替代。*/
            d[i]=a[j][i];
        }
        t++;
        
    }
    
    for(i=0;i     {
        sum+=s[i];
    }
    
    printf("%d\n",sum);
 }

你可能感兴趣的:(最小生成树)