数据结构实验之图论六:村村通公路(最小生成树之破圈法)

数据结构实验之图论六:村村通公路
Time Limit: 1000 ms Memory Limit: 65536 KiB
Submit Statistic Discuss
Problem Description

当前农村公路建设正如火如荼的展开,某乡镇政府决定实现村村通公路,工程师现有各个村落之间的原始道路统计数据表,表中列出了各村之间可以建设公路的若干条道路的成本,你的任务是根据给出的数据表,求使得每个村都有公路连通所需要的最低成本。
Input

连续多组数据输入,每组数据包括村落数目N(N <= 1000)和可供选择的道路数目M(M <= 3000),随后M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个村庄的编号和修建该道路的预算成本,村庄从1~N编号。
Output

输出使每个村庄都有公路连通所需要的最低成本,如果输入数据不能使所有村庄畅通,则输出-1,表示有些村庄之间没有路连通。
Sample Input

5 8
1 2 12
1 3 9
1 4 11
1 5 3
2 3 6
2 4 9
3 4 4
4 5 6
Sample Output

19
Hint

Source

xam

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define inf 199999999
int n,m,sum;
int vis[1001],mp[1001][1001],dis[1001];//dis是记录距离的,mp是记录到哪个点的距离的,
//vis是标记哪个结点被收进最小生成树了
void prim()
{
    int pos;
    int f=0;
    sum=0;
    memset(vis,0,sizeof(vis));//标记数组初始化
    for(int i=1;i<=n;i++)
    {
        dis[i]=mp[1][i];
    }//对每一条边进行赋值,直接相连的是他们之间的距离,否则就是无穷远;
    vis[1]=1;//标记
    for(int i=1;i<n;i++)
    {   int mm=inf;//要放在里面是因为,要比较N-1组数据,每一组的结点数都是不一样的,每一组要和本组的比较,和上一个组没有关系的
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&dis[j]<mm)
            {
                mm=dis[j];
                pos=j;
            }
        }//这个for就是找最小的dis
        vis[pos]=1;//进行标记
        if(mm==inf)
        {
            f=1;
            break;
        }//这里是表明这个图不连通,有孤立的点,如果到生成树里面所有的点的距离都是无穷远
        //不就是说明不和里面的任意的点直接相连嘛,不就是不连通嘛
        sum+=mm;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&dis[j]>mp[pos][j])//dis存到是每个点到固定点的距离,而mp存的是j到pos点的距离,是每次更新之后的
            {
                dis[j]=mp[pos][j];
            }
        }//我们比较每个结点的距离比较的是结点到这个最小生成树的距离,
        //也就是到数里面每个结点之间的距离,所以数据要进行更新,
        //例如,到第一个点的距离是无穷,那到第二个点的距离如果不是无穷,就要更新成这个数了
        //dis数组存的就是这个距离,mp数组存的是,举个栗子吧,mp[1][i]是所有i到1的距离,
        //存到dis数组里,mp[pos][i]是所有的i到pos的距离,如果i到1结点的距离是无穷远,而到
        //pos的距离是一个比无穷远的数小,那dis[i]里的数值就要更新成这个数值了
    }
    if(f==1)
    {
        printf("-1\n");
    }
    else printf("%d\n",sum);
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                {
                    mp[i][j]=0;
                }
                else mp[i][j]=inf;//邻接矩阵初始化
            }
        }
        int a,b,c;
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(mp[a][b]>c)//假如有重边,选取最小的
            {
                mp[a][b]=c;
                mp[b][a]=c;//无向图都要赋值的
            }
        }
        prim();//调用函数,别忘了
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/BHliuhan/article/details/80725398