局域网 -- 信息学奥赛一本通

文章讨论了一种针对无向图的问题,目标是找到并删除回路中权值最大的边,求解这些删除边的权值总和。使用Kruskal算法,从小到大排序边并构建最小生成树,当遇到已连通的节点时,选择较大的边进行删除。最后通过示例代码展示了如何实现这一算法。
摘要由CSDN通过智能技术生成

思路:

对于本题而言:n个点,k条边的无向图,连线之间权值越小越好,要求我们删除回路里,权值更大的边。然后求出所有删除的边的权值总和。
在这里插入图片描述
而我们的最小生成树算法:求的是连通路的最小权值总和。而本题要求的是最大权值和。
所以我们需要往最小生成树上转化。
给定了图,数据范围是稀疏图 – 首先排除的是邻接矩阵 – prime算法。
其次是对于边的选取,如果采用Kruskal算法,是将边从小到大排序的,那么这就恰好迎合了题意,从小到大利用边去连通两个点,当你遇到某条边上的两个点是已经连通了的,说明这两个点之间存在回路,由于是从小到大枚举每条边,所以此时发现的回路边自然更大,那么由题意可知,此时就是回路中所需要删除的权值更大的边在回路状态下。
故累计该边的权值即可。其他的按照Kruskal算法连接就行了。只需要加个特判处理。

代码:

Kruskal算法不会受到连通块的影响。

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e2 + 10, M = 2e2 + 10;
struct Edge{
    int a, b, c;
    bool operator < (const Edge& E) const{
        return c < E.c;
    }
}edge[M];
int n, k, p[N];

int find (int x)
{
    if (x != p[x]) 
        p[x] = find(p[x]);
    return p[x];
}

int kruskal()
{
    int res=0;
    
    for (int i=1; i <= n;  i++) p[i] = i;
    sort (edge+1, edge+1+k);
    for (int i=1; i <= k; i ++) //遍历边!
    {
        int a = edge[i].a, b = edge[i].b, w = edge[i].c;
        a = find(a), b = find(b);
        if (a != b)
        {
            p[a] = p[b];
        }
        else res += w;
    }
    
    return res;
}

int main()
{
    cin >> n >> k;
    
    for (int i=1; i <= k; i ++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        edge[i] = {a, b, c};    //存边!
    }
    
    cout << kruskal ();
    
    return 0;
}

prime算法:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值