A - 还是畅通工程(最小生成树)

点击打开链接


 

某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。 

Input测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。 
当N为0时,输入结束,该用例不被处理。 
Output对每个测试用例,在1行里输出最小的公路总长度。 
Sample Input

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

Sample Output

3
5


        
 
Huge input, scanf is recommended.

隔了那么长时间再来做这道题,还是犯了上次同样的错误,初始化parent数组

for(int i = 0; i <= n; i++)

这个地方一定是<=,一直不过真的很不爽,还是自己对代码不熟悉。

 

AC代码

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

using namespace std;

int parent[105]; //定义parent数组用来判断边与边是否形成环路
int sum;

struct Edge
{

    int beginn;
    int endd;
    int weight;

} edges[5005];

bool cmp(Edge a, Edge b)
{
    if(a.weight == b.weight)
        return a.beginn < b.beginn;
    else
        return a.weight < b.weight;
}

int Find(int f)
{
    while( parent[f] > 0 )
    {
        f = parent[f];
    }

    return f;

}

//Kruskal算法生成最小生成树
void MiniSpanTree_Kruskal(int x, int y)
{
    int i, n, m;

    for( i = 0; i <= x; i++ )
    {
        parent[i] = 0;
    }

    for( i = 0; i < y; i++ )
    {
        n = Find(edges[i].beginn);
        m = Find(edges[i].endd);

        if( n != m )    //如果n==m,则形成环路不满足!
        {
            parent[n] = m;      //将此边的结尾顶点放入下标为起点的parent数组中,表示此顶点已经在生成树集合中

            sum += edges[i].weight;
        }
    }

    printf("%d\n", sum);
}

int main()
{
    int t, i, ans;

    while(scanf("%d", &t) != EOF , t)
    {
        sum = 0;
        ans = t*(t - 1)/2;

        for( i = 0; i < ans; i++ )
        {
            scanf("%d %d %d", &edges[i].beginn, &edges[i].endd, &edges[i].weight);
        }

        sort(edges, edges+ans, cmp);

        MiniSpanTree_Kruskal(t, ans);

    }

    return 0;

}

 

还有一种叫做PRIM算法的也可以解这道题。

 

Kruskal算法

 

PRIM算法

 

posted @ 2017-08-03 16:26  Veritas_des_Liberty  阅读(279)  评论(0编辑  收藏  举报