例题11-2 苗条的生成树 UVa1395 Kruskal算法样例(基于并查集,which is almost like set)

1、题目链接
2、首先把权值排序。对于连续的边集区间[L,R],如果这些边使n个点全部连通(用并查集,逐步扩大连通集),则存在。
从小到大枚举L,从R=L开始,添加n个边,用并查集将这些边的端点合为一个并查集。

#include<iostream>  
#include<algorithm>  
#include<vector>  
using namespace std;  

#define N 5000+10  
#define INF 100000000  
int u[N], v[N], w[N];  //也可以struct edge 
int r[N], p[N];  
int n, m;  
int find(int x)  
{  
    return p[x] == x ? x : p[x] = find(p[x]);  
}  
int cmp(const int i, const int j)  
{  
    return w[i] < w[j];  
}  
int Kruskal(int L)  
{  
    int ans = -1;  
    int R;  
    for (int i = 1; i <= n; i++)//每构建一次即初始化一次并查集  
        p[i] = i;  
    for (R = L; R < m; R++)  
    {  
        int e = r[R];  
        int x = find(u[e]);  
        int y = find(v[e]);  
        if (x != y)  //不构成圈
        {  
            ans = max(ans, w[e] - w[r[L]]);  
            p[x] = y;  //合成树,即添加边 
        }  
    }  
    int fa = find(1);  
    for (int i = 1; i <= n; i++)//判断n个点是否都连通  
    if (fa != find(i))  
        return ans=INF;  
    return ans;//连通就返回  

}  
int main()  
{    
    while (cin >> n >> m && (n || m))  
    {  
        int ans = INF;  
        for (int i = 0; i < m; i++)  
            cin>>u[i]>>v[i]>>w[i];  //第i条边的数据 
        for (int i = 0; i < m; i++)  
            r[i] = i;  
        sort(r, r + m, cmp);  //注意此处排序i的意义
        if (m < n - 1)cout<<"-1\n";  
        else  
        {  
            for (int i = 0; i < m - n + 2; i++)  
                ans = min(ans, Kruskal(i));  
            if (ans == INF)  
                cout<<"-1\n";  
            else cout<<ans;  
        }  
    }  
    return 0; 
    } 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值