【最小生成树-Kruskal】POJ 3522 Slim Span

POJ 3522 Slim Span

  • 题意:给一幅图,要求找到其中一颗生成树使这个生成树上的最大边权和最小边权的差值最小。
  • 思路:核心是用Kruskal算法找最小生成树。
  1. 我们先将所有边的边权排序,我们要构成树,并且要使得树的最大最小边权差值尽量小,所以我们在排好序的边中取尽可能连续的V-1条边来构成树。
  2. E条边,最多最多我们只能有E-(V-1)+1=E-V+2棵树。我们依次遍历一遍找最小差值即可。
  3. 需要注意的是,排好序后的边,前面可以构成一棵树,但是越往后可能就不能构成树,所以我们找最小差值的时候要注意是不是存在树,所以我们要加上判断条件再来存最小差值。
  4. 还有就是,如果ans并没有更新,也就是说E-V+2<0,也就是给出的条件不能构成树。如果Kruskal(1)==-1也就是说给出的边虽然满足了E-V+2<0,但仍然一棵树都不能构成。
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define P(x) x>0?x:0
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxV=105;
const int maxE=5e3;
int V,E;
int root[maxV],high[maxV],size[maxV];
int Find(int x) { return root[x]==x ? x : root[x]=Find(root[x]); }
int Same(int x,int y) { return Find(x)==Find(y); }
void Merge(int x,int y)
{
    x=Find(x);
    y=Find(y);
    if(high[x]<high[y]||size[x]<size[y])
    {
        root[x]=y;
        size[y]+=size[x];
    }
    else
    {
        root[y]=x;
        size[x]+=size[y];
        if(high[x]==high[y]) high[x]++;
    }
}
struct node{
    int u,v,w;
    node(int a=0,int b=0,int c=0):u(a),v(b),w(c){}
    friend bool operator < (node n1,node n2) { return n1.w<n2.w; }
}ve[maxE];
void init()
{
    for(int i=1;i<=V;i++) { root[i]=i; high[i]=0; size[i]=1; }
}
int Kruskal(int x)
{
    init();
    int begin=ve[x].w,edge_num=0;
    for(int i=x;i<=E;i++)
    {
        if(!Same(ve[i].u,ve[i].v))
        {
            Merge(ve[i].u,ve[i].v);
            edge_num++;
            if(edge_num==V-1)
                return ve[i].w-begin;
        }
    }
    return -1;
}
int main()
{
    while(~scanf("%d%d",&V,&E) && (V||E))
    {
        init();
        for(int i=1;i<=E;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            ve[i]=node(a,b,c);
        }
        sort(ve+1,ve+E+1);
        int ans=INF;
        for(int i=1;i<=E-V+2;i++)
            if(Kruskal(i)!=-1)
                ans=min(ans,Kruskal(i));
        if(ans==INF||Kruskal(1)==-1) printf("-1\n");
        else printf("%d\n",ans);
    }
    return 0;
}

【吐槽POJ】
今天上午交的题,哎呀妈呀,从八点多钟就开始炸,一直wating交不了,等了一天(⊙﹏⊙)

你可能感兴趣的:(#,最小生成树,图论)