Slim Span (最小生成树)

我怕爱的太早我们不能终老 提交于 2020-03-08 09:36:04

题意

求生成树的最长边与最短边的差值的最小值

题解

最小生成树保证每一条边最小,就只要枚举最小边开始,跑最小生成树,最后一个值便是最大值

在枚举最小边同时维护差值最小,不断更新最小值。

C++代码

/**
/*@author Victor
/*language C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int , ll>
#define pli pair<ll,int>
#define pdl pair<double,ll>
#define pld pair<ll,double>
#define pdd pair<double,double>
#define iput(n) scanf("%d",&n);
#define dput(n) scanf("%lf",&n);
#define llput(n) scanf("%lld",&n);
#define cput(n) scanf("%s",n);
#define puti(n) printf("%d\n",n);
#define putll(n) printf("%lld\n",n);
#define putd(n) printf("%lfd\n",n);
#define _cls(n) memset(n,0,sizeof(n));
//求二进制中1的个数
//__builtin_popcount(n);
//求2^k
//#define (ll)Pow(2,k) (1LL<<k)

struct edge
{
    int u,v,cost;
}eg[100001];
int n,m;//,father[100001];

bool cmp(edge e1,edge e2)
{
    return e1.cost<e2.cost;
}

int par[N];        //父亲
int Rank[N];    //树的高度

//初始化n个元素
void init(int n)
{
    for(int i=0; i<=n; ++i)
    {
        par[i] = i;
        Rank[i] = 0;
    }
}
//查询树的根非递归实现
int find(int x)
{
    while(par[x]!=x)
        x=par[x];
    return x;
}
//合并x和y所属集合
void unite(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx==fy)
        return;
    if(Rank[fx]>Rank[fy])
        par[fx]=fy;
    else
    {
        par[fy]=fx;
        if(Rank[fx]==Rank[fy])
            Rank[x]++;
    }
}
//关于路径压缩
int find2(int x)
{
    int fx=find(x);
    int t;
    while(x!=fx)
    {
        t=par[x];
        par[x]=fx;
        x=t;
    }
    return fx;
}

// 最小生成树 Kruskal 算法
int minn;
int Kruskal()
{
    minn = 1e9;
    edge e;
    int i,res;
    sort(eg,eg+m,cmp);
    // 构建最小生成树
    for(int j = 0;j < m; j ++){ 
        
        init(n);res=0;
        
        for( i=j;i<m;++i )
        {
            e=eg[i];
            if( find(e.u)!=find(e.v) )
            {
                unite(e.u,e.v);
                
                if(++res == n - 1)
                    minn = min(minn,e.cost - eg[j].cost);
            }
        }
    }
    return res;
}


int main(){
    
    while(scanf("%d%d",&n,&m)&&n+m){
        
        for(int i = 0; i < m;++i){
            scanf("%d%d%d",&eg[i].u,&eg[i].v,&eg[i].cost);
        }
        int ans = Kruskal();
        bool flag = 1;
        
        if(minn != 1000000000) printf("%d\n",minn);
        else printf("-1\n");
    }
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!