最小生成树(MST)

Kraskal算法

1.初始所有节点都独立
2.按照边的权值递增遍历所有的边,若遍历到的边上的两个点,分属在不同的集合,则这条边就是最小生成树上的一条边,并将这两个顶点合并。
3.如果出现集合数量只为1个,说明最小生成树已经构成。如果遍历完所有的边,集合还大于1个,说明原图不连通,最小生成树不存在。

代码

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

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

struct edge{
    int a , b ,cost;
    bool operator < (const edge b)const{
        return cost<b.cost;
    }

}e[100*99/2];


int Tree[100],nodecount,ans;

int findRoot(int a){
    if(Tree[a]==-1){
        return a;
    }
    int root = findRoot(Tree[a]);
    Tree[a] = root;
    return root;
}

void unit(edge e){
    int a_root = findRoot(e.a);
    int b_root = findRoot(e.b);
    if(a_root!=b_root){
        Tree[a_root] = b_root;
        ans += e.cost;
        nodecount --;
    }
}

int main(){
    int N,a,b,cost,status;
    while(cin>>N&&N){
        nodecount = N;
        ans = 0;
        for(int i=1;i<=N;i++){
            Tree[i]=-1;
        }
        int M = N*(N-1)/2;
        for(int j=0;j<M;j++){
            cin>>a>>b>>cost>>status;
            e[j].a = a;
            e[j].b = b;
            if(status)  
                e[j].cost = 0;
            else
                e[j].cost = cost;
        }
        sort(e,e+M);
        for(int m=0;m<M;m++){
            unit(e[m]);
            if(nodecount==1)
                break;
        }
        printf("%d\n",ans);
    }
    return 0;

}
点赞