「LGOJ」村村通

题目描述

某市调查城镇交通状况,得到现有城镇道路统计表。表中列出了每条道路直接连通的城镇。市政府 "村村通工程" 的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要相互之间可达即可)。请你计算出最少还需要建设多少条道路?

Link

题解

可以用并查集来做

把互相连通的城市作为一个家族

然后路径压缩一下,把父亲指向根节点

最后统计一下有多少个家族

如果自己是自己家族的族长那么ans++

表明有一个家族

最后ans需要-1,因为三个家族只需要两条线就能连通

Code

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

#define RE register

int n,m,x1,x2,ans,fa[2000];

inline void fread(int &x){//快读
    x=0;
    int f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    x*=f;
}

inline int find(int x){//找父亲
    if(fa[x]==x)return x;
    return fa[x]=find(fa[x]);//路劲压缩
}

inline void merge(int x1,int x2){//合并
    int fa1=find(x1);
    int fa2=find(x2);
    if(fa1!=fa2)fa[fa1]=fa2;//如果不是同一个父亲就合并
}

int main(){
    while(1){
        ans=0;
        fread(n);
        if(n==0)return 0;
        fread(m);
        for(RE int i=1;i<=n;i++){
            fa[i]=i;
        }
        for(RE int i=1;i<=m;i++){
            fread(x1);
            fread(x2);
            merge(x1,x2);//合并两个城市
        }
        for(RE int i=1;i<=n;i++){
            if(fa[i]==i)ans++;//发现一个家族
        }
        printf("%d\n",ans-1);//记得-1
    }
    return 0;
}
posted @ 2021-08-13 11:28  sushitong  阅读(55)  评论(0)    收藏  举报