2-2 畅通工程之局部最小花费问题

有够水的,纯Kruskal板子题,注意有的村庄已经有路了,那么俩个直接合并集合就好了。

码风是以前的,比较难看

/*
第一步:先将所有边按权重从小到大排序
第二步:枚举每一条边a--b,权重是c,如果a--b不连通(a,b分别在一个集合中,但是a与b不连通)
    if(a,b不连通) 将这条边加入集合中
    其本质就是并查集 + 排序
*/
#include <iostream>
#include <algorithm>
#include <cstring>
 
using namespace std;
const int N = 100010, M = 200010, INF = 0x3f3f3f3f;
 
int p[N], n, m;
bool g[1010][1010];
 
struct Edge
{
    int a, b, w;
}edges[M];//存储边

bool cmp(Edge x, Edge y) {
    return x.w < y.w;
}
 
int find(int x)  // 并查集
{
    if (p[x] != x) p[x] = find(p[x]);//寻找祖宗节点并进行状态压缩
    return p[x];
}
 
int kruskal()
{
    sort(edges, edges + m, cmp);
    int res = 0, cnt = 0;//res记录路径长度,cnt记录用到的点数
    
    for (int i = 0; i < m; i ++ )
    {
        int a = edges[i].a, b = edges[i].b, w = edges[i].w;
        a = find(a), b = find(b);
        if(a != b)
        {
            p[a] = b;//如果两个点不联通,那么让他们连通
            res += w;
            cnt ++;
        }
    }
    //if (cnt < n - 1) return INF;//如果没有n - 1个点,说明没有连通
    return res;
}
 
int main()
{
    cin >> n;
    m = n * (n - 1 ) / 2;
    for (int i = 1; i <= n; i ++ )  p[i] = i;// 初始化并查集,初始时候每一个点都是独立的集合,即自己就是根节点
    for (int i = 0; i < m; i ++ )
    {
        int a, b, x, w;
        cin >> a >> b >> w >> x;
        if(x == 1)  p[find(a)] = find(b);
        edges[i] = {a, b, w};
    }
    int t = kruskal();
    cout << t << endl;
    
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值