POJ 3522

//题目大意:求一棵生成树让最大边最小边差值最小
//题目类型:最小生成树+枚举
//解题思路:分析可知生成树一定是最小生成树,利用Kruskal算法枚举所有的最小生成树
#include <iostream>
#include <algorithm>
//#include <conio.h>
using namespace std;
#define narray 101
#define marray 5000
const int INF = 0x7fffffff;
typedef struct edge
{
    int a;
    int b;
    int w;
}edge;
edge edges[marray];
int final[narray];
int cnt[narray];
int n,m;
bool cmp(const edge a,const edge b)
{
     return a.w<b.w;
}
int findp(int n)
{
    if(final[n]==n)
        return n;
    else
        final[n]=findp(final[n]);
    return final[n];
}
bool Union(int a,int b)
{
     int roota = findp(a);
     int rootb = findp(b);
     if(roota!=rootb)
     {
         if(cnt[a]>=cnt[b])
         {
             final[rootb] = roota;
             cnt[roota]+=cnt[rootb];
         }
         else
         {
             final[roota] = rootb;
             cnt[rootb]+=cnt[roota];
         }
         return true;
     }
     else
         return false;
}
int main()
{
    //freopen("1.txt","r",stdin);
    int a,b,w;
    int i,j;
    int num;
    int minslim;
    int firstw,lastw;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        if(n==0 && m==0) break;
        minslim = INF;
        for(i=1;i<=m;++i)
        {
            scanf("%d%d%d",&edges[i].a,&edges[i].b,&edges[i].w);           
        }       
        sort(edges+1,edges+m+1,cmp);
        bool flag = false;
        if(n==2 && m==1)            //注意考虑只有两个顶点一条边的情况
        {
             printf("0\n");  
             continue;
        }
        for(j=1;j<=m;++j)     //枚举
        {
            num = 0;
            for(i=1;i<=n;++i)
            {
                final[i] = i;
                cnt[i] = 1;
            }
            for(i=j;i<=m;++i)
            {
                if(j+n-2>m)  //剪枝
                {
                   flag = true;
                   break;
                }
                a = edges[i].a;
                b = edges[i].b;
                w = edges[i].w;
                if(Union(a,b))
                {
                    num++;
                    if(num==1)
                       firstw = w;   
                    else if(num==n-1)
                    {
                       lastw = w;
                       if(lastw-firstw<minslim)
                          minslim = lastw-firstw;
                       break;
                    }
                }
            }  
            if(flag)
              break;
        }
        if(minslim == INF)  printf("-1\n");      
        else printf("%d\n",minslim);       
    }
    //getch();
    return 0;
}

posted @ 2010-06-09 21:45  北海小龙  阅读(568)  评论(0编辑  收藏  举报