7-11 畅通工程之局部最小花费问题(最小生成树+并查集)

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

输入格式:

输入的第一行给出村庄数目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<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef struct Node{
    int mt1;
    int mt2;
    int fee;
    int sense;
}Node;
Node e[10001];
int f[101];
bool cmp(Node a,Node b){
    return a.fee < b.fee;
}
void init(int n){
    for(int i = 1;i <= n;i++)
        f[i] = i;
    return;
}
int getf(int x){
    if(f[x] == x)
        return x;
    f[x] = getf(f[x]);
    return f[x];
}
int merge(int a,int b){
    int tx = getf(a);
    int ty = getf(b);
    if(tx != ty){
        f[ty] = tx;
        return 1;
    }
    return 0;
}
int main(){
    int n, sm = 0,cnt = 0;
    scanf("%d",&n);
    int m = n * (n - 1) / 2;
    for(int i = 0;i < m;i++)
        scanf("%d%d%d%d",&e[i].mt1,&e[i].mt2,&e[i].fee,&e[i].sense);
    sort(e,e + m,cmp);//默认权值从小到大对边进行排序
    init(n);//初始化
    //优先访问已经修建过的,因为已经修建过的花费的费用为0!!!!!前者之鉴,后事之师 
    for(int i = 0;i < m;i++)
        if(e[i].sense==1)
          merge(e[i].mt1,e[i].mt2)==1 ? cnt++ : cnt;
    for(int i = 0; i< m;i++){//从小到大枚举每一条边
        if(merge(e[i].mt1,e[i].mt2)){
            if(!e[i].sense)
                sm += e[i].fee;
            cnt++;//计数器
        }
        if(cnt == n - 1)//知道选用了 n - 1条边
            break;
    }
    printf("%d\n",sm);
    return 0;
}
    原文作者:道路修建问题
    原文地址: https://blog.csdn.net/qq_37708702/article/details/78874998
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞