畅通工程的最低成本 | 克鲁斯卡尔(并查集)

Description

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

Input

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

Output

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

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<vector>
#include<algorithm>
using namespace std;

int n;//村庄数
int m;//村庄间的路的总数


struct Edge {
    int u;              //边的起始顶点
    int v;              //边的终止顶点
    int w;              //边的权值
    bool operator<(const Edge& e) const {
        return w < e.w; //用于按w递增排序
    }
};                      //边集
Edge E[50 * 99];

typedef struct node {
    int rank;   //结点对应秩,当前结点到叶节点的个数
    int parent; //结点对应双亲下标
}UFSTree;       //并查集树的结点类型
UFSTree t[50];

int FIND_SET(int x) {   //在x所在子树中查找根的编号
    if (x != t[x].parent)
        return(FIND_SET(t[x].parent));
    else
        return(x);
}

void UNION(int x, int y) {//合并两颗生成树为一颗
    if (t[x].rank > t[y].rank)
        t[y].parent = x;
    else {
        t[x].parent = y;
        if (t[x].rank == t[y].rank)
            t[y].rank++;
    }
}


//用于按w递增排序
//bool cmp(Edge a, Edge b) {
//    return a.v < b.v;
//}

void Kruskal() {
    int sum = 0;//路的修建成本
    sort(E, E + m);//按照路的修建成本从低到高排序

    for (int i = 1; i <= n; i++) {//初始化t
        t[i].rank = 0;
        t[i].parent = i;
    }
    
    int k = 1;
    int j = 0;
    int ul, vl, sn1, sn2;
    while (k < n) {
        ul = E[j].u;
        vl = E[j].v;
        sn1 = FIND_SET(ul);
        sn2 = FIND_SET(vl);
        if (sn1 != sn2) {
            k++;
            sum += E[j].w;
            UNION(sn1, sn2);
        }
        j++;
    }
    cout << sum << endl;
}

int main()
{
    while (cin >> n) {
        if (n == 0)break;
        m = n * (n - 1) * 0.5;
        int a, b, v, t;
        for (int i = 0; i < n * (n - 1) / 2; i++) {
            cin >> a >> b >> v >> t;
            E[i] = { a,b,v };
            if (t == 1) E[i].w = 0;//已修建
        }
        Kruskal();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值