[是题解哦] 洛谷 P1536 村村通

题目链接

点这里ww

 

题目描述

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

 

输入输出格式

输入格式:

每个输入文件包含若干组测试测试数据,每组测试数据的第一行给出两个用空格隔开的正整数,分别是城镇数目N(N<1000)和道路数目M;随后的M行对应M条道路,每行给出一对用空格隔开的正整数,分别是该条道路直接相连的两个城镇的编号。简单起见,城镇从1到N编号。

注意:两个城市间可以有多条道路相通。例如:3 3 1 2 1 2 2 1这组数据也是合法的。

当N为0时,输入结束。

输出格式:

对于每组数据,对应一行一个整数。表示最少还需要建设的道路数目。

 

题解

这道题我大概有两种思路。

  • 并查集求集合个数
  • Tarjan求强连通分量个数

并查集

我们可以考虑使用并查集建立集合。

由题目可获得n棵树,要想所有村庄都联通,需要这n棵树相连,这n棵树相连最少需要n-1条边。

Tarjan

由题目可知图中存在n个联通块。

由无向图可知联通块均为强连通分量。

Tarjan算法的思路和并查集差不多,求出强连通分量的个数n,这n个强连通分量联通需要n-1条边。

但是我懒得写Tarjan。

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 int n,m;
 6 int f[2010];
 7 
 8 inline int find(int k){
 9     return f[k]==k?k:f[k]=find(f[k]);
10 }
11 
12 void unionn(int x,int y){
13     x=find(x);
14     y=find(y);
15     f[x]=y;
16 }
17 
18 int main(){
19     scanf("%d",&n);
20     while(n!=0){
21         scanf("%d",&m);
22         for(int i=1;i<=n;i++)
23             f[i]=i;
24         for(int i=1;i<=m;i++){
25             register int u,v;
26             scanf("%d%d",&u,&v);
27             u=find(u);
28             v=find(v);
29             if(u!=v)
30                 unionn(u,v);
31         }
32         int ans=0;
33         for(int i=1;i<=n;i++)
34             if(f[i]==i) //如果自己的父亲是自己,就存在一个集合
35                 ans++;
36         printf("%d\n",ans-1);
37         scanf("%d",&n);
38     }
39     return 0;
40 }

 

友情链接:安利一只小姐姐的博客

 

posted @ 2018-09-22 18:50  多多良小伞  阅读(181)  评论(0编辑  收藏  举报