1. 程式人生 > 實用技巧 >P1536 村村通

P1536 村村通

題目描述

某市調查城鎮交通狀況,得到現有城鎮道路統計表。表中列出了每條道路直接連通的城鎮。市政府 "村村通工程" 的目標是使全市任何兩個城鎮間都可以實現交通(但不一定有直接的道路相連,只要相互之間可達即可)。請你計算出最少還需要建設多少條道路?

輸入格式

輸入包含若干組測試測試資料,每組測試資料的第一行給出兩個用空格隔開的正整數,分別是城鎮數目nn和道路數目mm;隨後的mm行對應mm條道路,每行給出一對用空格隔開的正整數,分別是該條道路直接相連的兩個城鎮的編號。簡單起見,城鎮從11到nn編號。

注意:兩個城市間可以有多條道路相通。

輸出格式

對於每組資料,對應一行一個整數。表示最少還需要建設的道路數目。

輸入輸出樣例

輸入 #1
4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0

輸出 #1

1
0
2
998

程式碼:

#include<iostream>
#include<cstdio>
using namespace std;
int n=1,m;//n代表有多少個村莊,m是代表已有多少條路
int f[10000];//儲存每個節點的“祖先”
void init()//預處理,一開始把每個結點的祖先設為自己
{
    for(int i=1;i<=n;i++)f[i]=i;
    //千萬不能在輸入前用此函式(n都沒輸入怎麼預處理)
} int find_(int x)//用到了路徑壓縮,比單純的while更快 { if(f[x]==x)//如果x的祖先是自己 retrun x;//那麼返回x就好了。 return find_(f[x]);//如果不是的話,x的祖先的祖先就是x的祖先 } void union_(int x,int y)//合併x,y兩個結點 { f[find_(y)]=find_(x);//讓x的祖先成為y的祖先的祖先,這樣y所在的集合裡所有結點的祖先全變為x的祖先。 } int main() { while(n!=0) { scanf("%d",&n);//
輸入n if(n!=0)//判斷n是否等於0 scanf("%d",&m);//是就輸入m else//否則就跳過 continue; if(m==0)//如果m(路的條數)等於0的話,那麼想必就沒有路了 { printf("%d\n",n-1);//連起n個節點最少就要n-1條線 continue; } init();//預處理 int x,y;//定義x城鎮的y城鎮的編號 int sum=0;//用於儲存最少的路徑條數 int a[10000]={0};//桶,用於記錄有多少個沒有路徑的城鎮 for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y);//輸入x and y的編號 union_(x,y);//因為x y之間有路線了,就合併它們 } for(int i=1;i<=n;i++)//開始判斷 { int c=find_(i);//判斷編號為c的城鎮的“祖先” if(!a[c])//如果這個“祖先”的編號沒有被記錄過的話 a[c]++,sum++;//那麼就記錄它,節點數加一。 } printf("%d\n",sum-1);//因為有n個不同的集合,那麼就至少要n-1條邊才能把它們連起來。 } return 0; }

#include <bits/stdc++.h>
using namespace std;
int pre[1000001],n,m,ans;
inline int Find(int x){
    return pre[x]==x?x:pre[x]=Find(pre[x]);
}
inline void Union(int x, int y){
    int fx=Find(x),fy=Find(y);
    if(fx!=fy) pre[fx]=fy;
}
int main()
{
    while(scanf("%d",&n)&&n){
        ans=0;
        scanf("%d", &m);
        for(int i=1;i<=n;i++) pre[i]=i;
        for(int i=1,x,y;i<=m;i++){
            scanf("%d%d",&x,&y);
            Union(x,y); 
        }
        for(int i=1;i<=n;i++){
            if(Find(i)==i) ans++;
        }
        printf("%d\n",ans-1);
    }
    return 0;
}