poj 3522 Kruskal

题意:求图的一个生成树使其最大边权与最小边权的差值最小,求其最小值

 

思路:利用贪心思想,先对边进行排序,然后从最小边开始枚举,每次进行kruskal向右加入边,若加入边刚好能遍历所有点,记录最后加入的边与第一个边的差值。最后得到最小值。

 

在kruskal枚举第一个边的时候没有加入判断是否剩下的边能够组成一个树,结果WA了几次,但是怎么觉得不加也没所谓呢。。?

 

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define MAXN 50050
#define inf 1000000000
using namespace std;

int pre[108];
int n,m,temp;int l,r;int ans;
struct Edge{
    int x,y,len;
}edge[MAXN];
int cmp(Edge a,Edge b)
{
    return a.len<b.len;
}
int find(int x)
{
    if(x!=pre[x])
        pre[x]=find(pre[x]);
    return pre[x];
}
void kruskal(int x)
{
    int num;
    for(int i=1;i<=n;i++)
        pre[i]=i;
    l=edge[x].len;num=0;
    //cout<<l<<endl;
    for(int i=x;i<=temp;i++)
    {

        int a=find(edge[i].x);
        int b=find(edge[i].y);
        if(a!=b)
        {
            pre[a]=b;
            num++;

        }
        if(num==n-1)
        {
            r=edge[i].len;
            if(ans>r-l)ans=r-l;
            //cout<<ans<<endl;
            return ;
        }
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)
            break;
        ans=20050;
        for(int i=0;i<m;i++)
        {
            int v,w,c;
            scanf("%d%d%d",&v,&w,&c);
            edge[i].x=v;
            edge[i].y=w;
            edge[i].len=c;
            temp=i;
        }
        sort(edge,edge+temp+1,cmp);
        //cout<<edge[0].len<<' '<<edge[temp].len<<endl;
        for(int i=0;i<=temp&&m-i>=n-1;i++)
            {kruskal(i);if(ans==0)break;}
        if(ans!=20050)
        printf("%d\n",ans);
        else printf("-1\n");
    }
    return 0;
}


 

posted @ 2013-07-31 20:57  amourjun  阅读(141)  评论(0编辑  收藏  举报