天天看點

UVA 1395 Kruskal算法

點選打開連結 模闆題

Kruskal算法是求最小生成樹的較為高效的算法,首先根據邊的權值從小到大排序,n個頂點的最小生成樹需要n-1條邊,周遊排序後的邊,若兩個頂點不連通則加入這條邊(可用反證法證明),知道加入了n-1條邊,用并查集将聯通的頂點放在一個集合裡,并查集把集合按樹的形式放在一個集合裡。

題意:n個頂點,m條邊,每條邊有權值,求最小生成樹。

分析:先判斷m條邊能否是n個頂點聯通,能則存在最小生成樹,否則不存在輸出-1.

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int,int> pa;
const int maxn=105;
int parent[maxn];
struct Edge
{
    int a,b,w;
    bool operator<(const Edge& u)const
    {
        return w<u.w;
    }
}edge[5000];
int n,m;
int find(int x)
{
    return parent[x]==x?x:parent[x]=find(parent[x]);
}
bool un(int i,int j)
{
    int x=find(i);
    int y=find(j);
    if(x==y)
        return false;
    parent[x]=y;
    return true;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)
            break;
        for(int i=1;i<=n;i++)
            parent[i]=i;
        int e=0;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&edge[e].a,&edge[e].b,&edge[e].w);
            un(edge[e].a,edge[e].b);
            e++;
        }
        int d=0;
        for(int i=1;i<=n;i++)
        {
            if(parent[i]==i)
                d++;
        }
        if(d>1)
        {
            printf("-1\n");
            continue;
        }
        sort(edge,edge+m);
        int ans=inf;
        bool flag=true;
        for(int l=0;l<m;l++)
        {
            for(int i=1;i<=n;i++)
                parent[i]=i;
            un(edge[l].a,edge[l].b);
            int mi=edge[l].w;
            int p=1;
            if(p==n-1)
            {
                printf("0\n");
                flag=false;
                break;
            }
            for(int r=l+1;r<m;r++)
            {
                if(un(edge[r].a,edge[r].b))
                {
                    p++;
                    if(p==n-1)
                    {
                        ans=min(ans,edge[r].w-mi);
                        break;
                    }
                }
            }
        }
        if(flag)
            printf("%d\n",ans);
    }
    return 0;
}