首页 > 代码库 > uva 1395 - Slim Span poj 3522 Slim Span(最小生成树算法)

uva 1395 - Slim Span poj 3522 Slim Span(最小生成树算法)

最近学习了一下 最小生成树 算法。

所谓最小生成树算法,就是给出一个连通图g[ maxn ][ maxn  ], 找出这个连通图的边权和最小的生成图(树)。

可以实现这个目的的算法,我叫它最小生成树算法。kruskal算法就是我学到的一种实现这种功能的算法。

对于kruskal算法的描述以及简单的证明在刘汝佳第二版上已经说得够明白

本题就是求 最小生成树 里面的 最大边权和最小边权 相差最小的最小生成树。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define mem(a) memset(a,0,sizeof(a))
const int maxn = 105 * 105;
int m,n;
int u[maxn],v[maxn],w[maxn],r[maxn];
int p[maxn];

int cmp(const int i,const int j){
    return w[i]<w[j];
}
int find_(int x){
    return p[x]==x?x:p[x]=find_(p[x]);
}
int kruskal(int start){
    int cnt = 0;
    mem(p);
    for(int i=1;i<=n;i++) p[i]=i;
    for(int i=start;i<m;i++){
        int e=r[i];
        int x=find_(u[e]);
        int y=find_(v[e]);
        if(x!=y){
            cnt++;
            p[x]=y;
        }
        if(cnt==n-1)
            return i;
    }
    return -1;
}

int main()
{
//    freopen("out.txt","w",stdout);
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0&&m==0)
            break;
        mem(r);mem(u);mem(v);mem(w);
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&u[i],&v[i],&w[i]);
        }
        for(int i=0;i<m;i++) r[i]=i;
        sort(r,r+m,cmp);
        int temp,ans;
        temp = kruskal(0);
        if(temp==-1){
            puts("-1");
            continue;
        }
        else{
            int e1=r[0];
            int e2=r[temp];
            ans=w[e2]-w[e1];
        }
        for(int i=1;i<m;i++){
            temp = kruskal(i);
            if(temp!=-1){
                int e1=r[i];
                int e2=r[temp];
                ans=min(ans,w[e2]-w[e1]);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


题目对时间按的要求并不是很严格,因此采用 排序后直接枚举 的方法。


uva 1395 - Slim Span poj 3522 Slim Span(最小生成树算法)