【图论】[CQBZOJ1362] 苗条的生成树
题目描述:点击此处
解题思路:
构造最小生成树,并计算苗条度,然后不断删最短边,用kruskal构造最小生成树,计算苗条度,直至图不再连通,输出苗条度。
若一开始就不是一棵树,则输出-1;
因为kruskal是贪心的算法,所以确定了最小边之后,最大边也随之确定,且最大边最小。
实现代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXM 5000
#define INF 0x7fffffff
#define MAXN 100
void Read(int &x){
char c;
while(c=getchar(),c!=EOF)
if(c>='0'&&c<='9'){
x=c-'0';
while(c=getchar(),c>='0'&&c<='9')
x=x*10+c-'0';
ungetc(c,stdin);
return;
}
}
int n,m,fa[MAXN+10],ans;
struct node{
int u,v,wt;
bool operator<(const node &x)const{
return wt<x.wt;
}
}edge[MAXM+10];
void read(){
Read(n),Read(m);
int i,u,v,wt;
for(i=1;i<=m;i++){
Read(u),Read(v),Read(wt);
edge[i].u=u,edge[i].v=v,edge[i].wt=wt;
}
sort(edge+1,edge+m+1);
}
int find(int x){
return fa[x]=(fa[x]!=x)?find(fa[x]):x;
}
int kruskal(int s){
int maxe=INF+1,mine=INF,i,u,v,wt,cnt=1;
for(i=1;i<=n;i++)
fa[i]=i;
for(i=s;i<=m;i++){
u=edge[i].u,v=edge[i].v,wt=edge[i].wt;
if(find(u)==find(v))
continue;
fa[fa[u]]=fa[v];
maxe=max(wt,maxe);
mine=min(wt,mine);
cnt++;
if(cnt==n)
break;
}
if(cnt<n)
return -1;
return maxe-mine;
}
int main()
{
while(1){
ans=INF;
read();
if(!n)
return 0;
int i,t;
for(i=1;i<=m;i++){
t=kruskal(i);
if(t==-1)
break;
if(t<ans)
ans=t;
if(!ans)
break;
}
if(ans==INF)
puts("-1");
else
printf("%d\n",ans);
}
}