UVA-1395+苗条生成树+变形Kruskal算法

Slim Span
Definition Of Slim Span
最苗条生成树的定义:生成树的中最大边与最小边的差值尽可能小。
要求:
①首先必须是一棵树。
②目标值是差值最小。

思路:朴素的想法就是暴力枚举所有可能的“苗条度最小生成树”,更新苗条度值即可。
时间复杂度:O((m-n)m*logm)
注意到,n≤100,所以这个时间复杂度是可以容忍的。

其他细节在注释里。

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=105;  //数组要开够
int n,m,fa[maxn];
struct Edge{
    int u,v,cost;
}t[maxn*maxn];

bool cmp(Edge a,Edge b){
    return a.cost<b.cost;
}

int find(int x){
    return (x==fa[x])?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
    fa[find(x)]=find(y);
}

void init()
{
    for(int i=1;i<=n;i++) fa[i]=i;
}

int main(){
    while(cin>>n>>m&& (n||m)){
    	//
        if(m==0 || n==0)
        {
            printf("%d\n",-1);
            continue;
        }
        for(int i=1;i<=m;i++){
            int u,v,cost;
            scanf("%d%d%d",&u,&v,&cost);
            t[i].u=u;t[i].v=v;t[i].cost=cost;
        }
        init();
        sort(t+1,t+m+1,cmp);
        int ans=1e7;
        for(int l=1;l<=m-n+2;l++)
        {
            int cnt=0;
            init();  //不要忘记每次并查集的初始化
            int mmin=1e7,mmax=-1,temp=0;
            for(int i=l;i<=m;i++)
            {
                int u=t[i].u,v=t[i].v;
                if(find(u)!=find(v))
                {
                    mmax=max(mmax,t[i].cost);
                    mmin=min(mmin,t[i].cost);
                    temp=max(temp,mmax-mmin);   //中间临时值取max
                    merge(u,v);
                    cnt++;  
                    if(cnt==n-1) //图的条件是恰有n-1条边
                    {
                        ans=min(ans,temp);
                        break;
                    }
                }
            }
        }
        if(ans==1e7) printf("%d\n",-1);
        else printf("%d\n",ans);
    }
    return 0;
}

ps:这种类型的题目像是一种求 max_min(或者是min_max)的问题,也就是求出方案中某种最大值尽可能最小的问题,如果有合法方案的话。

发布了67 篇原创文章 · 获赞 0 · 访问量 1525

猜你喜欢

转载自blog.csdn.net/qq_44846324/article/details/104504305