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)的问题,也就是求出方案中某种最大值尽可能最小的问题,如果有合法方案的话。