Slim Span (最小生成树)

题意

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

题解

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

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

C++代码

/**
/*@author Victor
/*language C++
*/
#include 
#include
#include
#include
#include
#include
#include<string>
#include
#include
#include
#include
#include
#include
#include
#include
#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
#define pll pair
#define pil pair
#define pli pair
#define pdl pair
#define pld pair
#define pdd pair
#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<

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;ii )
        {
            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");
    }
}

 

转载于:https://www.cnblogs.com/DWVictor/p/11228659.html

你可能感兴趣的:(Slim Span (最小生成树))