HDU 1232 畅通工程
并查集系列题目:http://acm.hdu.edu.cn/problemclass.php?id=721
畅通工程
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 20380 Accepted Submission(s): 10543
Problem Description
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?
Input
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
注意:两个城市之间可以有多条道路相通,也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。
Output
对每个测试用例,在1行里输出最少还需要建设的道路数目。
Sample Input
4 2 1 3 4 3 3 3 1 2 1 3 2 3 5 2 1 2 3 5 999 0 0
Sample Output
1 0 2 998
Hint Huge input, scanf is recommended.
自己写的代码:
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define maxn 1001
int id[maxn];
void init(){
int i;
for(i=0;i<maxn;i++)
id[i]=-1;
}
int find_root(int x){
if(id[x]==-1)
return x;
else
id[x]=find_root(id[x]);
return id[x];
}
void Union(int x,int y){
int rx=find_root(x);
int ry=find_root(y);
if(rx==ry) return;
id[ry]=rx;
}
int main(){
int n,m,a,b,sum,i;
while(scanf("%d",&n)!=EOF && n!=0){
scanf("%d",&m);
init();
while(m--){
scanf("%d %d",&a,&b);
Union(a,b);
}
sum=0;
for(i=1;i<=n;i++)
sum+=(id[i]==-1);
printf("%d\n",sum-1);
}
}另一个版本:
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define maxn 1001
int id[maxn];
int rank[maxn];
void init(){
int i;
for(i=0;i<maxn;i++){
id[i]=-1;
rank[i]=1;
}
}
int find_root(int x){
if(id[x]==-1)
return x;
else
id[x]=find_root(id[x]);
return id[x];
}
void Union(int x,int y){
int rx=find_root(x);
int ry=find_root(y);
if(rx==ry) return;
if(rank[rx]>rank[ry]){
id[ry]=rx;
rank[rx]+=rank[ry];
}
else{
id[rx]=ry;
rank[ry]+=rank[rx];
}
}
int main(){
int n,m,a,b,sum,i;
while(scanf("%d",&n)!=EOF && n!=0){
scanf("%d",&m);
init(); while(m--){
scanf("%d %d",&a,&b);
Union(a,b);
}
sum=0;
for(i=1;i<=n;i++)
sum+=(id[i]==-1);
printf("%d\n",sum-1);
}
}结果见下图:
他人模板:
1: //并查集+路径压缩+加权优化树
2: #include<iostream>3: using namespace std;
4: const int maxn = 1001;
5: int parent[maxn];
6: void Make_set(){
7: for(int i=0;i<maxn;i++)
8: parent[i]=-1; 9: } 10: int Find(int x){ //查找+非递归的路径压缩
11: int s=x;
12: while(parent[s]>0) s=parent[s];
13: while(x!=s){ //路径压缩
14: int temp=parent[x];
15: parent[x]=s; 16: x=temp; 17: } 18: return x;
19: } 20: void Union(int R1, int R2){
21: int r1=Find(R1), r2=Find(R2);
22: if(r1==r2) return;
23: int temp=parent[r1]+parent[r2];
24: //parent[r1]<0 && parent[r2]<0
25: if(parent[r1]>parent[r2]){
26: parent[r1]=r2; 27: parent[r2]=temp; 28: }29: else{
30: parent[r2]=r1; 31: parent[r1]=temp; 32: } 33: } 34: int main(){
35: //freopen("in.txt","r",stdin);
36: for(int n,m,a,b;cin>>n&& n!=0;){
37: Make_set(); 38: cin>>m;39: while(m--){
40: cin>>a>>b; 41: Union(a,b); 42: }43: int num=0;
44: for(int i=1;i<=n;i++)
45: if(parent[i]<0) num++;
46: cout<<num-1<<'\n';
47: } 48: }吉林大学版:
1: //Abstract: UFSet
2: //Author:Lifeng Wang (Fandywang)
3: // Model One 与Model 2 路径压缩方式不同,合并标准不同
4: const int MAXSIZE = 500010;
5: int rank[MAXSIZE]; // 节点高度的上界
6: int parent[MAXSIZE]; // 根节点
7: int FindSet(int x){// 查找+递归的路径压缩
8: if( x != parent[x] ) parent[x] = FindSet(parent[x]);
9: return parent[x];
10: } 11: void Union(int root1, int root2){
12: int x = FindSet(root1), y = FindSet(root2);
13: if( x == y ) return ;
14: if( rank[x] > rank[y] ) parent[y] = x;
15: else{
16: parent[x] = y; 17: if( rank[x] == rank[y] ) ++rank[y];
18: } 19: } 20: void Initi(void){
21: memset(rank, 0, sizeof(rank));
22: for( int i=0; i < MAXSIZE; ++i ) parent[i] = i;
23: } 24: //Model Two
25: const int MAXSIZE = 30001;
26: int pre[MAXSIZE]; //根节点i,pre[i] = -num,其中num是该树的节点数目;
27: //非根节点j,pre[j] = k,其中k是j的父节点
28: int Find(int x){//查找+非递归的路径压缩
29: int p = x;
30: while( pre[p] > 0 ) p = pre[p];
31: while( x != p ){
32: int temp = pre[x]; pre[x] = p; x = temp;
33: } 34: return x;
35: } 36: void Union(int r1, int r2){
37: int a = Find(r1); int b = Find(r2);
38: if( a == b ) return ;
39: //加权规则合并
40: if( pre[a] < pre[b] ){
41: pre[a] += pre[b]; pre[b] = a; 42: } 43: else {
44: pre[b] += pre[a]; pre[a] = b; 45: } 46: } 47: void Initi(void)
48: { 49: for( int i=0; i < MAXSIZE; ++i ) pre[i] = -1;
50: }


浙公网安备 33010602011771号