最优生成树 并查集和贪心的运用

本文介绍了一种基于贪心算法的最小生成树求解方法,包括最小生成树、最大生成树及瓶颈生成树的实现,并通过具体实例展示了如何使用并查集解决相关问题。

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

【问题描述】

给出N个顶点、E条边的连通无向简单图,请你完成下列任务:

任务1、求边权和最小的生成树(最小生成树)

任务2、求边权和最大的生成树(最大生成树)

任务3、求最大边最小的生成树(瓶颈生成树)

任务4、求最小边最大的生成树(瓶颈生成树)

【输入格式】

  第一行:两个整数N,E(N<=50000,E<=100000),分别表示有N个新岛,E对能直接用电缆连接的岛屿,其中主岛为1。
  接下来M行:每行三个数u,v,w,1<=u,v<=N,表示岛屿u和v之间可以直接用电缆连接,距离为w(<=100000)。

【输出格式】

  第一行一个整数,表示最小生成树的边权和;
  第二行一个整数,表示最大生成树的边权和;
  第三行一个整数,表示最大边最小的生成树中,最大边的权值;
  第四行一个整数,表示最小边最大的生成树中,最小边的权值;

【输入样例】

5 8
1 2 2
1 3 12
1 4 10
2 3 8
2 5 9
3 4 6
3 5 3
4 5 7

【输出样例】

19
39
8
8

【数据范围】

N<=50000,E<=100000

用并查集的方法,用贪心的思想从一头开始加边。
详见代码解释:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=50005;
struct shu
{
    int u,v,w;
};
vector<shu>g;
int n,m,fa[maxn];

bool my(shu a,shu b)
{
    return a.w<b.w;
}

void init()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        g.push_back((shu){x,y,z});
    }
    sort(g.begin(),g.end(),my);
}
void in()
{
    for(int i=0;i<=n;i++)
    fa[i]=i;
}

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

int main()
{
    //freopen("in.txt","r",stdin);
    init();
    in();
    int t=n-1;
    int ans=0,q;
    for(int i=0;i<g.size();i++)
    {
        if(find(g[i].u)==find(g[i].v)) continue;//如果已经连通就不用加边了。
        fa[find(g[i].u)]=find(g[i].v);
        t--;//只加n-1条边。
        ans+=g[i].w;
        if(t==0)
        {
            q=g[i].w;//最后一条边一定是最大的。
            break;
        }
    }
    printf("%d\n",ans);
    t=n-1;
    ans=0;
    int p;
    in();
    for(int i=g.size()-1;i>=0;i--)
    {
        if(find(g[i].u)==find(g[i].v)) continue;
        fa[find(g[i].u)]=find(g[i].v);
        t--;
        ans+=g[i].w;
        if(t==0)
        {
            p=g[i].w;
            break;
        }
    }
    printf("%d\n%d\n%d",ans,q,p);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值