【ACM】- POJ-1861 Network 【最小生成树】

本文深入探讨了最小生成树问题的解决策略,特别是在寻找生成树中最小最长边的应用场景下。通过Kruskal算法结合并查集的方法,文章提供了一个C++实现的详细示例,展示了如何高效地处理此类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接
题目分析

最小生成树问题,不过要求得不是路径和,而是使生成树中的最长边最小;
| 细节:
1、结点编号1~N
2、注意题目给的测试数据有BUG;

解题思路

Kruskal算法 + 并查集;


AC程序(C++)
/**********************************
*@ID: 3stone
*@ACM: POJ-1861 Network
*@Time: 18/9/15
*@IDE: VSCode + clang++
***********************************/
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;

const int maxn = 1010;

struct edge{
    int u, v, cost;
    edge() {}
    edge(int _u, int _v, int _cost) : u(_u), v(_v), cost(_cost) {}
    bool operator < (const edge& n) const {//规定优先级,形成小顶堆
        return cost > n.cost;
    }
};

int N, M;
int far[maxn]; //并查集
vector<edge> route; //保存生成树的边

//寻根
int find_root(int a) {
    int root = a;
    while(root != far[root]) root = far[root];
    while(a != far[a]) {
        int cur = a;
        a = far[a];
        far[cur] = root;
    }
    return root;
}


int kruskal(priority_queue<edge> E) {
    int ans = 0;
    int edge_num = 0;
    while(!E.empty()) {
        edge e = E.top(); E.pop();
        int root_u = find_root(e.u);
        int root_v = find_root(e.v);
        if(root_u != root_v) {
            edge_num++;
            route.push_back(e); //保存加入的边
            far[root_v] = root_u; //合并集合
            if(edge_num == N - 1) {
                ans = e.cost; //保存最后一个最大边即可;
                break;
            }
        }
    }//while
    if(edge_num == N - 1) return ans;
    else return -1;
}


int main() {
    int a, b, cost;
    while(scanf("%d %d", &N, &M) != EOF) {
        priority_queue<edge> E;
        route.clear(); //清空路径
        for(int i = 0; i < M; i++) {//输入边信息
            scanf("%d%d%d", &a, &b, &cost);
            E.push(edge(a, b, cost));   
        }

        for(int i = 1; i <= N; i++) far[i] = i; //初始化并查集
        int ans = kruskal(E); //需要先输出最大边,那么就需要保存所有边了吗?
        printf("%d\n", ans);
        printf("%d\n", route.size());
        for(int i = 0; i < route.size(); i++) {
            edge e = route[i];
            printf("%d %d\n", e.u, e.v);
        }

    }//while

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值