Slim Span
题目大意:
给出m条边,问使n个节点连成一幅连通图的最大边减去最小边的最小值
思路:
对边按照边权排序,求出在边权从小到大的边序列中连续的可以使点连成图的边的最大值与最小值之差。再求暴力对比。
AC代码:
#include<algorithm>
#include<cstdio>
#include<iostream>
using namespace std;
const int inf=0x3f3f3f3f;
struct Edge{
int u,v,w;
Edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){}
friend bool operator<(Edge a,Edge b)
{
return a.w<b.w;
}
}edge[10005];
int cnt;
int fa[105];
int n;
void rebuild()
{
for(int i=1;i<=n;i++){
fa[i]=i;
}
}
int find(int x)
{
return fa[x]==x?x:fa[x]=find(fa[x]);
}
bool merge(int x,int y)
{
int fx(find(x)),fy(find(y));
if(fx==fy) return false;
fa[fx]=fy;
return true;
}
void build(Edge e)
{
if(merge(e.u,e.v))cnt--;
}
int main()
{
int m;
while(~scanf("%d%d",&n,&m)&&(n||m))
{
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
edge[i]=Edge(u,v,w);
}
sort(edge+1,edge+1+m);
int l,r;
int flag=1;
int minn=inf;
for(l=1;l<=m;l++)
{
rebuild();
cnt=n;
r=l;
while(cnt>=2)
{
if(r==m+1){
flag=0;
break;
}
build(edge[r]);
r++;
}
if(!flag) break;
minn=min(minn,edge[r-1].w-edge[l].w);
}
if(minn==inf) printf("-1\n");
else printf("%d\n",minn);
}
}