畅通工程问题(prim最小生成树)

某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建快速路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全地区畅通需要的最低成本。

输入格式:

输入的第一行给出村庄数目N (1≤N≤100);随后的N(N−1)/2行对应村庄间道路的成本及修建状态:每行给出4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态 — 1表示已建,0表示未建。

输出格式:

输出全省畅通需要的最低成本。

输入样例:

4

1 2 1 1

1 3 4 0

1 4 1 1

2 3 3 0

2 4 2 1

3 4 5 0

输出样例:

3

#include <stdio.h>
#include <memory.h>
#define inf 0x3f3f3f3f
/*
全省畅通,最小生成树prim算法
这道题的关键在于有的道路是已建有的道路未建
解决方法就是:将已建的道路的成本置为0,这样在建造最小生成树时,就有花费为0的已连通的道路
*/
//prim算法也是贪心的原则,每次将到生成树的距离最小的点纳入到树中
int n,sum;
int map[101][101];
int dis[101];//表示生成的树到当前点的距离(成本)
void prim()
{
    int vis[101];
    memset(dis,inf,sizeof(dis));
    memset(vis,0,sizeof(vis));
    //从1开始
    for(int i=1;i<=n;i++)
    {
        dis[i]=map[1][i];
    }
    vis[1]=1;
    for(int i=1;i<=n-1;i++)//成为联通图至少需要n-1条边
    {
        int mind=inf,minn=1;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&dis[j]<mind)
            {
                mind=dis[j];
                minn=j;
            }
        }
        sum+=mind;//记下生成树每条边是值
        vis[minn]=1;//找到建成最小生成树花费最小的城市minn,将minn标记为生成树成员
        for(int j=1;j<=n;j++)
        {
            //在还没纳入树的点中查找到
            if(!vis[j]&&map[minn][j]<dis[j])
            {
                dis[j]=map[minn][j];
            }
        }
    }
}
int main()
{
    int u,v,c,f;
    scanf("%d",&n);
    memset(map,inf,sizeof(map));
    for(int i=1;i<=n*(n-1)/2;i++)
    {
        scanf("%d%d%d%d",&u,&v,&c,&f);
        //这条路已建则将这条路的花费置为0
        if(f==1) map[u][v]=map[v][u]=0;
        else map[u][v]=map[v][u]=c;//无方向
    }
    prim();
    printf("%d\n",sum);
    return 0;
}

上一篇:jenkins权限配置


下一篇:leetcode:1024. 视频拼接(中等,贪心)