Hdu 1863.畅通工程 Kruskal模板

题目描述

畅通工程

解题思路

给出n边,m点,求最小消耗,可以套用最小生成树模板来做
最小生成树主要可以用Prim和Kruskal解决

  • Prim时间复杂度是O(n2),n是顶点数量,和边数量无关,主要用于稠密图
  • Kruskal时间复杂度是O(eloge),e是边数量,和顶点数量无关,主要用于稀疏图
  • Kruskal的核心操作在于查并集,而且是对边进行的操作
  • 查并集可见我上篇博客中的练习题LeetCode:Friend Circles 查并集
  • Kruskal依次选出边长最小的,判断边上两点是不是同一个集合(find),如果不是,则连到一个集合中去(union),终止条件是集合中:边数=顶点数-1,说明是一个最小生成树

代码

本题中输入是邻接表
可套作kruskal模板(但也不全适用,目前比较精简)

#include <iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
#define max 111
struct node{//边
    int u,v,w;
}edge[max];
int n,m,fa[max];
int cmp(node a,node b){
    return a.w<b.w;
}
void init(){
    for(int i=0;i<m;i++){
        fa[i] = i;
    }
}
int find(int x){
    if(x==fa[x]) {
        return x;
    }else{
        return fa[x]=find(fa[x]);
    }
}
void _union(int x,int y){
    x = find(x);
    y = find(y);
    if(x!=y){
        fa[y] = x;
    }
}
int main() {
    freopen("in.txt","r",stdin);
    while(1){
        int count=0,ans=0;
        cin>>n>>m;//n边m点
        if(n==0) break;
        init();
        for(int i=0;i<n;i++){
            cin>>edge[i].u>>edge[i].v>>edge[i].w;
        }
        sort(edge,edge+n,cmp);//边从小到大排序
        for(int i=0;i<n;i++){
            if(find(edge[i].u)!=find(edge[i].v)){//对边进行操作
                _union(edge[i].u,edge[i].v);
                count++;
                ans+=edge[i].w;//这里根据题意写
            }
        }
        if(count==m-1){
            cout<<ans<<endl;
        }else{
            cout<<"?"<<endl;
        }   
    }
    fclose(stdin);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/armstrong_rose/article/details/80315404