最小生成树kruskal POJ 3522 Slim Span

题目:https://odzkskevi.qnssl.com/8e16f8701018d0e3529ac3ca319e1f67?v=1502277241
最简单的kruskal,主要参考紫书代码
kruskal算法就是先给边按权值大小排序,然后从小到大遍历,用并查集判断边上的两个点是否在同一集合,如果不是的话将其添加进去,直到所有的点都加入到集合中。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=10000;
int u[maxn],v[maxn],w[maxn],r[maxn],p[105];
int n,m;
bool cmp(int a,int b)
{
    return w[a]<w[b];
}
int find(int x)
{
    return p[x]==x?x:p[x]=find(p[x]);
}
int kruskal()
{
    int ans=INF,ok=0;
    for(int i=1;i<=n;i++) p[i]=i;
    for(int i=0;i<m;i++) r[i]=i;
    sort(r,r+m,cmp);                  //间接排序
    for(int i=0;i<m;i++)
    {
        int num=0;
        for(int j=1;j<=n;j++) p[j]=j;
        for(int j=i;j<m;j++)
        {
            int e=r[j],x=find(u[e]),y=find(v[e]);
            if(x!=y)               
            {
                p[x]=y;
                num++;
            }
            if(num==n-1)
            {
                ans=min(ans,w[r[j]]-w[r[i]]);
                ok=1;
                break;
            }
        }
    }
    if(ok==1)
        return ans;
    else
        return -1;
}
int main()
{
    while(cin>>n>>m)
    {
        if(n==0)
            break;
        for(int i=0;i<m;i++)
            cin>>u[i]>>v[i]>>w[i];
        cout<<kruskal()<<endl;
    }
}
原文地址:https://www.cnblogs.com/acagain/p/9180728.html