给定一个无向网,求最小权差生成树的权差

12 篇文章 0 订阅
5 篇文章 5 订阅

给定一个无向网,求最小权差生成树的权差

参考博客

题目

问题描述:

最小生成树(MST)是图论中一个常见而简单的问题。本题要求的最小权差生成树比MST更难一些。

给定一个无向网,以及它的一棵生成树。定义该生成树的权差为:权值最大的边 – 权值最小的边。

给定一个无向网,求最小权差生成树的权差。

输入描述:

输入文件中包含多个测试数据。输入文件第一行为一个正整数T,为测试数据的个数。

每个测试数据描述了一个无向网,第一行为两个正整数n和m,2<n≤200,m≤5000,分别表示无向网中的顶点数和边数;接下来有m行,每行描述了一条无向边,为3个整数,u v w,0<u, v≤n(即顶点序号从1开始计起),0<w≤100 000 000,表示一条连接顶点u和v的无向边,权值为w。任何两个顶点间最多只有一条边相连。无向网是连通的,且任何两个顶点之间最多只有一条边。

输出描述:

对输入文件中的每个测试数据,输出求得的最小权差生成树的权差。

样例输入:样例输出:
1
3 3**
1 2 10
1 3 20
**2 3 30
10

CODE

#include<iostream>
#include<algorithm>

#define MAXN 105
#define MAXM 10005
#define INF 1000000000//定义无限大

using namespace std;

int n, m;
int fa[MAXN];
struct node
{
    int x, y, w;
    bool operator <(const node& a) const {
        return w < a.w;//根据边的权重有小到大排序
    }
}e[MAXM];

int find(int x)
{
    if (fa[x] == x) return x;
    int t = find(fa[x]);//压缩路径
    fa[x] = t;
    return t;
}

int main()
{
    int nn;
    scanf("%d", &nn);
    for (int ii = 0; ii < nn; ii++) {
        scanf("%d%d", &n, &m);
            for (int i = 0; i < m; ++i)
                scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].w);//存储边
            sort(e, e + m);//根据权重排序
            int ans = INF;
            for (int i = 0; i <= m - n + 1; i++) {//多次更新最小生成树
                int tmp = -1, sum = 0;
                for (int j = 1; j <= n; ++j) fa[j] = j;//初始化,每个点都是单独一个集合
                for (int j = i; j < m; ++j) {
                    int tx = find(e[j].x), ty = find(e[j].y);
                    if (tx != ty) {
                        sum++;
                        fa[tx] = ty;
                        if (sum == n - 1) {
                            tmp = e[j].w - e[i].w;
                            break;
                        }
                    }
                }
                if (tmp != -1 && tmp < ans) ans = tmp;
            }
            if (ans < INF) printf("%d\n", ans);
            else printf("-1\n");
    }
    
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值