UVa 1395 - Slim Span --生成树入门题

题目链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4141
问题的意思是叫你找到一颗生成树,生成树的值定义为权重最大的一条边 Wmax 减去权重最小的一条边 Wmin ,使生成树的值最小,输入和输出看原题,顶点个数 n<=100 ,边 m<(n1)n/2 可以估算出 m<5000 .
分析
由于这道题的边数不是很大,可以用枚举的方式固定一条最小边,再找权重比他大的边用Kruskal的算法构造生成树。
简单分析一下复杂度。最小边最多小于5000种,每种情况最多找99条边。也就是说在 O(105) 界内能够找到
代码

#include
#include
#include
#define INF 0x3f3f3f3f
#define maxe 50010
#define maxn 109
using namespace std;

int nv,ne;
struct Edge{
    int u,v,w;
    bool operator<(Edge& o)
    {
        return w//set
int p[maxn];

int find(int a)
{
    return p[a] ==a? a:p[a] = find(p[a]); 
}

void union_set(int x,int y)
{
    x = find(x);
    y = find(y);
    if(x!=y)
        p[x] = y;
}



int main()
{
    //freopen("H:\\c++\\file\\stdin.txt","r",stdin);

    while(scanf("%d %d",&nv,&ne)&&nv)
    {
        for(int i=0 ; i<ne ; ++i)scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w);
        if(ne1){
            printf("-1\n");
            continue;
        }

        sort(edge,edge+ne);


        int ans = INF;
        for(int l = ne - nv+1 ; l>=0 ;--l)
        {
            int max = l;
            int cnt=1;
            //生成树 
            for(int i=1 ; i<=nv ; ++i )p[i] = i;
            union_set(edge[l].u,edge[l].v);
            while(cnt1)
            {
                max++;
                if(max>=ne){
                    break;
                }else
                {
                    int x = find(edge[max].u);
                    int y = find(edge[max].v);
                    if(x!=y)
                    {
                        cnt++;
                        union_set(x,y);
                    }
                }

            }
            if(cnt==nv-1&&ans>edge[max].w-edge[l].w)ans= edge[max].w-edge[l].w;
        }
        if(ans == INF)printf("-1\n");
        else printf("%d\n",ans);
    }


    return 0;
}

你可能感兴趣的:(算法刷题)