题解 UVa10842(Kruskal)

Posted s-t-a-r-d-u-s-t

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 UVa10842(Kruskal)相关的知识,希望对你有一定的参考价值。

大生成树。

这题几乎就是模板。看我翻译:

一个城市由N个节点,M条带权无向边组成。城市连通。由于公路养护部门预算不足,需要在城市连通的情况下关闭尽可能多的道路,且使剩余权值最小的道路权值尽可能大。求出这个权值。

因为图要连通,边要最少且边权尽量大,显然我们将要得到的是图的最大生成树。用Kruskal好求。

Kruskal通过将边排序,借助并查集判断当前边是否多余(不能有环)来尽量把更小(大)的边放入生成树。还有一种算法叫Prim求生成树。

代码:

#include<bits/stdc++.h>
using namespace std;
struct node

    int a,b,d;
edge[20000];
bool cmp(node x,node y)

    return x.d>y.d;


int n,m,father[6000],ans,num;
int find(int x)//寻找祖先

    if(father[x]-x)
        father[x]=find(father[x]);
    return father[x];


void pt(int x,int y)//合并

    x=find(x);
    y=find(y);
    father[y]=x;


bool check(int x,int y)//判断是否连通

    x=find(x);
    y=find(y);
    if(x==y)
        return 1;
    else
        return 0;


int main()

    int t;
    cin>>t;
    for(int f=1;f<=t;f++)
    
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            father[i]=i;
        for(int i=1;i<=m;i++)
        
            int x,y,w;
            cin>>x>>y>>w;
            edge[i].a=x;
            edge[i].b=y;
            edge[i].d=w;
        //建图,不需要邻接矩阵或邻接表,这样就行了,也好排序
        
        sort(edge+1,edge+1+m,cmp);//排序
        for(int i=1;i<=m;i++)
            if(find(edge[i].a)-find(edge[i].b))//并查集操作
            
                pt(edge[i].a,edge[i].b);//连通
                ans=edge[i].d;//由于已经排序,边长单减,后加的边必定更小,因此直接更新答案。
                num++;
                if(num==n-1)//对于树,边数为点数减1
                    break;
            
        
        printf("Case #%d: %d\n",f,ans);
        num=ans=0;//输出答案后记得清0
    
    
    return 0;

以上是关于题解 UVa10842(Kruskal)的主要内容,如果未能解决你的问题,请参考以下文章

Buy or Build UVA - 1151

UVA 1359 POJ 3522 Slim Span(最小生成树kruskal)

UVa 1395 苗条的生成树(Kruskal+并查集)

UVA10462Is There A Second Way Left? —— 次小生成树 kruskal算法

Connect the Campus (Uva 10397 Prim || Kruskal + 并查集)

POJ1679 The Unique MST 题解 次小生成树 题解 Kruskal+暴力LCA解法(因为倍增不会写)