EDITORIAL:
目の前で言えば、エントリと検索セット、そして今のは、特定のトピックを見てみましょう、とコードを書くために、および調査セットの理解を深めて思いました。
HDU1232--スムーズな交通プロジェクト
問題の説明
既存のテーブルを取得するための都市交通の地方の調査では、都市部の道路は、テーブルには、都市や町に直接接続された各道路を示しています。ターゲット州政府「円滑な交通プロジェクト」(あなたが道路を介して間接的に相互に到達できる限り、必ずしも直接道路に接続していない)任意の2つの町の間で地域がトラフィックを実装できるようにすることです。最小も構築する必要がありますどのように多くの道路尋ねましたか?
入力
テスト入力には、いくつかのテストケースが含まれています。各テストケースは、町N(<1000)と道路番号Mの数であり、最初の2つの正の整数の列が与えられ、次のMパスに対応するM個の行は、各列は、正の整数の組が与えられ、それぞれ、数直接通信経路における2つの町。簡単にするため、町は1からNまでの番号
注:道路の数が2つの都市の間で通信することができる、すなわち、
3 3
1 2
1 2
2 1
この入力が有効である
Nが0である場合、入力端、ユースケースが処理されません。出力
各テストケースのために、出力中の少なくとも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
0
2
998ヒント
巨大な入力は、scanfのが推奨されます。
ソース
トピックへのリンク:http://acm.hdu.edu.cn/showproblem.php?pid=1232
参照コード:
1互いに素なセット - 圧縮パスは、連結ランクです]
// 31MS 1384K 864 B G++ 【路径压缩,按秩合并】
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m;
int t1,t2;
int parent[1005];// 树型结构的根节点
int r[1005];// 秩
//【并查集中的<查>】
// 路径压缩
int find_parent(int p)
{
if(parent[p]!=p)parent[p]=find_parent(parent[p]);
return parent[p];
}
//【并查集中的<并>】
// 按秩合并
void unite(int x,int y)
{
int root_x=find_parent(x);
int root_y=find_parent(y);
if(root_x==root_y)return;
if(r[root_x]>r[root_y])parent[root_y]=root_x;
else
{
parent[root_x]=root_y;
if(r[root_x]==r[root_y])r[root_y]++;
}
}
// 计算有多少个联通分量
int get_ans(int num)
{
int sum=0;
for(int i=1;i<=num;i++)
{
if(parent[i]==i)sum++;
}
return sum;
}
int main()
{
while(~scanf("%d",&n) && n)
{
for(int i=1;i<=n;i++)
{
parent[i]=i;
r[i]=0;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&t1,&t2);
unite(t1,t2);
}
printf("%d\n",get_ans(n)-1); // 最后结果需要减1
// (这个应该比较好理解,例如有n个点,只需要n-1条线段就能将它们连起来)
}
}
2. [互いに素なセット - パス圧縮]
// 31MS 1388K 853 B G++ 【按秩合并】
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m;
int t1,t2;
int parent[1005];
int r[1005];
int find_parent(int p)
{
if(parent[p]==p)return p;
return find_parent(parent[p]);
}
void unite(int x,int y)
{
int root_x=find_parent(x);
int root_y=find_parent(y);
if(root_x==root_y)return;
if(r[root_x]>r[root_y])parent[root_y]=root_x;
else
{
parent[root_x]=root_y;
if(r[root_x]==r[root_y])r[root_y]++;
}
}
int get_ans(int num)
{
int sum=0;
for(int i=1;i<=num;i++)
{
if(parent[i]==i)sum++;
}
return sum;
}
int main()
{
while(~scanf("%d",&n) && n)
{
for(int i=1;i<=n;i++)
{
parent[i]=i;
r[i]=0;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&t1,&t2);
unite(t1,t2);
}
printf("%d\n",get_ans(n)-1);
}
}
3簡単互いに素なセット]
// 15MS 1384K 725B G++ 【朴素并查集】
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m;
int t1,t2;
int parent[1005];
int find_parent(int p)
{
if(parent[p]==p)return p;
return find_parent(parent[p]);
}
void unite(int x,int y)
{
int root_x=find_parent(x);
int root_y=find_parent(y);
if(root_x==root_y)return;
else parent[root_y]=root_x;
}
int get_ans(int num)
{
int sum=0;
for(int i=1;i<=num;i++)
{
if(parent[i]==i)sum++;
}
return sum;
}
int main()
{
while(~scanf("%d",&n) && n)
{
for(int i=1;i<=n;i++)
{
parent[i]=i;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&t1,&t2);
unite(t1,t2);
}
printf("%d\n",get_ans(n)-1);
}
}
最後に書かれました:
テンプレートのタイトルは上のグラフ、中国聯通のコンポーネントの数を求め、実際には、ばらばらのセットです。
ユニコムのコンポーネントは何ですか?ここに掲載のブログを、あなたがに見て指すことができます。(怠惰な良い、あなた自身を書きたくはありません)