算法之最小生成树(继续畅通工程)

个人比较爱好刷算法题,然后最近遇到一个算法题,是最小生成树的问题,是继续畅通工程,首先先看下具体要求:

省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。

输入描述:

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

    当N为0时输入结束。

输出描述:

    每个测试用例的输出占一行,输出全省畅通需要的最低成本。

示例1

输入

31 2 1 01 3 2 02 3 4 031 2 1 01 3 2 02 3 4 131 2 1 01 3 2 12 3 4 10

输出

310然后分析,这个题的实际就是最小生成树的问题,可以采用prim算法和kruskal算法,然后最后计算生成树的边数的总和,则就是要的结果,但是这个题比较巧妙的是又添加了一个附加条件,则是有的路已经修了,所以这个需要在输入的时候做一点点小小的改动,那就是对于已经修好的路,我们需要将其边的权重设置为0,这样,则不需要在原算法上做任何修改,则可以实现。使用的prim算法(具体的prim算法的思路这里不再阐述了)
#include <stdio.h>

using namespace std;//定义这个图的存储方式,个人比较喜欢用矩阵的方式,也可以使用邻接表的方法int tree[100][100];//记录点遍历的信息
bool isFind[100];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF && n!=0)
    {     //初始化数据
        for(int i = 0;i<n;i++)
        {
            for(int j = 0; j<n;j++)
               tree[i][j] = -1;
            isFind[i] = false;
        }     //输入数据,做一个小操作,如果输入为1,则权重为0
        for(int i =0 ; i< n*(n-1)/2;i++)
        {
            int a,b,c,d;
            scanf("%d %d %d %d",&a,&b,&c,&d);
            if(d == 1)
            {
                c = 0;
            }
            tree[a-1][b-1] = c;
            tree[b-1][a-1] = c;
        }     //用来统计路径
        int countDistance = 0;
        while(true)
        {
            int minDistance = 10000;
            int minNode = 0;            //找寻当前未遍历的点中最短的路径
            for(int i = 1 ;i<n;i++)
            {
                if(!isFind[i]&&minDistance>tree[0][i])
                {
                    minDistance = tree[0][i];
                    minNode = i;
                }
            }       //更新相关数据,遍历信息和总长度信息
            isFind[minNode] = true;
            countDistance += minDistance;
            int isResult = true;       //判断是否已经遍历完所有的点,是则退出,否则继续循环
            for(int i = 1 ;i<n;i++)
            {
                if(!isFind[i])
                    isResult = false;
            }
            if(isResult)
                break;            //如果没有遍历完,更新当前树与未遍历的点的信息
            for(int i = 1;i<n;i++)
            {
                if(!isFind[i])
                {
                    if(tree[minNode][i]<tree[0][i])
                        tree[0][i] = tree[minNode][i];
                }
            }
        }
        printf("%d\n",countDistance);
    }
    return 0;
}

下面则是kruskal算法的实现:

#include<stdio.h>
#include<algorithm>

using namespace std;
#define N 101
int Tree[N];

struct Edge {
    int a, b;//边两个顶点的编号
    int cost;//该边的权值

    bool operator<(const Edge &A) const {//重载小于号使其可以按照边权从小到大排序
        return cost < A.cost;
    }
} edge[6000];

int findRoot(int x) {//查找代表集合的树的根节点
    if (Tree[x] == -1) {
        return x;
    } else {
        int temp = findRoot(Tree[x]);
        Tree[x] = temp;
        return temp;
    }
}

int main() {
    int n;
    while (scanf("%d", &n) != EOF && n != 0) {
        int m = n * (n - 1) / 2;
        int d;
        for (int i = 1; i <= m; i++) {
            scanf("%d %d %d %d", &edge[i].a,
                  &edge[i].b, &edge[i].cost,&d);
            if(d == 1)
                edge[i].cost = 0;
        }
        sort(edge + 1, edge + m + 1);
        for (int i = 1; i <= N; i++) {
            Tree[i] = -1;
        }
        int count = 0;//最小生成树上边权的和,初始值为0
        for (int i = 1; i <= m; i++) {//按照边权值递增排序遍历所有的边
            int aRoot = findRoot(edge[i].a);
            int bRoot = findRoot(edge[i].b);//查找两个顶点的集合信息
            if (aRoot != bRoot) {
                Tree[aRoot] = bRoot;//合并两个集合
                count += edge[i].cost;//累加该边权值
            }
        }
        printf("%d\n", count);//输出
    }

    return 0;
}

  

  

				
时间: 2024-10-14 05:34:26

算法之最小生成树(继续畅通工程)的相关文章

[最小生成树] 继续畅通工程

题目描述 省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可).现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态.现请你编写程序,计算出全省畅通需要的最低成本. 输入 测试输入包含若干测试用例.每个测试用例的第1行给出村庄数目N ( 1< N < 100 ):随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到

hdu 1863 畅通工程 kruskal || prim

简单最小生成树,畅通工程,这三道题目都是练习最小生成树的. 注意一下判断是否有通路时,kruskal可以判断每个点的祖先是否相同,prim可以判断每个点是否都加进集合里面了,也就是说是否都访问过.prim算法要把没有给的边初始化为MAX无穷大... 代码:(kruskal) #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath>

hdoj 1233 还是畅通工程

并查集+最小生成树 还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 29762    Accepted Submission(s): 13297 Problem Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直

hdu 1875 畅通工程再续(kruskal算法计算最小生成树)

畅通工程再续 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 18411    Accepted Submission(s): 5769 Problem Description 相信大家都听说一个"百岛湖"的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现.现在政府决定大力发展百岛湖,发展首先

还是畅通工程(peime算法最小生成树)

个人心得:就是最小生成树的运用,还是要理解好每次都是从已搭建好的生成树里面选择与她的补集中最短距离,所以那个book数组的更新 需要好生体会.不过还是有缺陷,算法的复杂度为O(n^2),看介绍说用优先队列加堆会达到O(n*long n),不过很可惜看不懂,太菜了 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小.请计算最小的

poj1258 Agri-Net +hdu 1233 还是畅通工程 (最小生成树Prime算法)

Agri-Net Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 43215   Accepted: 17683 Description Farmer John has been elected mayor of his town! One of his campaign promises was to bring internet connectivity to all farms in the area. He nee

hdu 1233(还是畅通工程)(prime算法,克鲁斯卡尔算法)(并查集,最小生成树)

还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 26860    Accepted Submission(s): 11985 Problem Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路

HDU 1233 还是畅通工程【最小生成树入门题,Kruskal算法+Prim算法】

还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 39929    Accepted Submission(s): 18144 Problem Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路

HDU 1875 畅通工程再续【最小生成树,Prime算法+Kruskal算法】

畅通工程再续 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 24151    Accepted Submission(s): 7808 Problem Description 相信大家都听说一个"百岛湖"的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现.现在政府决定大力发展百岛湖,发展首先