poj 3522 生成树的变形

【题意】

求一颗生成树,使得边权的最大值与最小值之差最小。

【题解】

可以二分答案,但是没必要,只要枚举最小边即可。

使用kruskal的贪心法,得到的生成树的最大边必定最小,所以最大边与最小边之差最小。

【代码】

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100;
const int maxe=maxn*(maxn-1)/2;

struct edge
{
       int x,y,w;
}e[maxe];
int fa[maxn];
int n,m;

int find(int x)
{
    if (fa[x]==x) return x;
    fa[x]=find(fa[x]);
    return fa[x];
}

int kruskal(int st)
{
    int i,x,y,num=n,ans=-1;
    for (i=1;i<=n;i++)
        fa[i]=i;
    for (i=st;i<m;i++)
    {
        x=find(e[i].x);
        y=find(e[i].y);
        if (x==y) continue;
        fa[x]=y;
        num--;
        if (num==1) 
        {
           ans=e[i].w;
           break;
        }
    }
    return ans-e[st].w;
}

int cmp(edge a,edge b)
{
    return a.w<b.w;
}

int main()
{
    freopen("pin.txt","r",stdin);
    freopen("pou.txt","w",stdout);
    int ans,i,tt;
    while (scanf("%d%d",&n,&m)!=EOF)
    {
          if (n==0 && m==0) break;
          for (i=0;i<m;i++)
              scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
          sort(e,e+m,cmp);
          ans=kruskal(0);
          if (ans<0)
          {
                      printf("%d\n",-1);
                      continue;
          }
          for (i=1;i<m;i++)
          {
              tt=kruskal(i);
              if (tt<0) break;
              if (tt<ans) ans=tt;
          }
          printf("%d\n",ans);
    }
    return 0;
}     


没有更多推荐了,返回首页