上大物學了會並查集,感覺挺簡單的,而且很好玩,繼dfs,bfs和floyd演算法外又學了一種求連通塊的演算法,綜合下來這幾種演算法各有優劣吧.
並查集演算法詳解見此
模板如下:
#include
using
namespace std;
#define maxn 100001
int father[maxn]
,rank_[maxn]
;void
init
(int n)
}int
find_
(int x)
return father[x]
?x:(father[x]
=find_
(father[x]))
;}void
merge_
(int i,
int j)
else
if(rank_[x]
==rank_[y]
&&x!=y) rank_[y]++;
}int
main()
例題1
洛谷p1551 親戚
題目背景這道題非常簡單,只需要簡單的應用即可若某個家族人員過於龐大,要判斷兩個是否是親戚,確實還很不容易,現在給出某個親戚關係圖,求任意給出的兩個人是否具有親戚關係。
*題目描述 規定:x和y是親戚,y和z是親戚,那麼x和z也是親戚。如果x,y是親戚,那麼x的親戚都是y的親戚,y的親戚也都是x的親戚。
*輸入格式 第一行:三個整數n,m,p,(n<=5000,m<=5000,p<=5000),分別表示有n個人,m個親戚關係,詢問p對親戚關係。
*以下m行:每行兩個數mi,mj,1<=mi,mj<=n,表示mi和mj具有親戚關係。*
接下來p行:每行兩個數pi,pj,詢問pi和pj是否具有親戚關係。
*輸出格式 p行,每行乙個』yes』或』no』。表示第i個詢問的答案為「具有」或「不具有」親戚關係。
*輸入輸出樣例 輸入 #1
6 5 3
1 21 5
3 45 2
1 31 4
2 35 6
輸出 #1
yesyes
no
**
#include
using
namespace std;
#define maxn 50010
int father[maxn]
,rank_[maxn]
;void
init
(int n)
}int
find_
(int x)
return x==father[x]
?x:(father[x]
=find_
(father[x]))
;}void
merge_
(int i,
int j)
else
if(rank_[x]
==rank_[y]
&&x!=y) rank_[y]++;
}int
main()
for(
int i=
0;i)return0;
}
例題2
洛谷p1551 親戚
題目背景若某個家族人員過於龐大,要判斷兩個是否是親戚,確實還很不容易,現在給出某個親戚關係圖,求任意給出的兩個人是否具有親戚關係。
*題目描述 規定:x和y是親戚,y和z是親戚,那麼x和z也是親戚。如果x,y是親戚,那麼x的親戚都是y的親戚,y的親戚也都是x的親戚。
*輸入格式 第一行:三個整數n,m,p,(n<=5000,m<=5000,p<=5000),分別表示有n個人,m個親戚關係,詢問p對親戚關係。
*以下m行:每行兩個數mi,mj,1<=mi,mj<=n,表示mi和mj具有親戚關係。
*接下來p行:每行兩個數pi,pj,詢問pi和pj是否具有親戚關係。
*輸出格式 p行,每行乙個』yes』或』no』。表示第i個詢問的答案為「具有」或「不具有」親戚關係。
*輸入輸出樣例 輸入 #1
6 5 3
1 21 5
3 45 2
1 31 4
2 35 6
輸出 #1
yesyes
no**
#include
using
namespace std;
#define maxn 1010
int t;
int father[maxn]
,rank_[maxn]
;int n,h,r,x[maxn]
,y[maxn]
,z[maxn]
,sp[maxn]
;void
init
(int n)
memset
(x,0
,sizeof
(x))
;memset
(y,0
,sizeof
(y))
;memset
(z,0
,sizeof
(z))
;memset
(sp,0,
sizeof
(sp));
}int
find_
(int x)
void
merge_
(int i,
int j)
else
if(rank_[x]
==rank_[y]
&&x!=y) rank_[y]++;
}boolis(
int i,
int j)
intmain()
}for
(int i=
0;i)merge_
(i,j);}
}}for(
int i=
0;i} cout<<
"no"
memset
(sp,0,
sizeof
(sp));
}return0;
}
這題稍微複雜一點,但是用了並查集還是非常簡單
本來想法,昨天剛搭建完主題,結果今天就說要整改…18到25號整改一周,這一周先發csdn吧…
演算法學習 並查集
大家肯定有聽說過社交網路裡面的六人理論吧,說是可以通過六個人的聯絡認識世界上的任意乙個人。比如我想認識一下機械系的系花,我先找到機械系的朋友,然後通過朋友介紹認識。這樣可以發現我們的社交圈子其實是有部分重疊的。當然也有可能是我的圈子太小,根本沒有什麼朋友認識那個圈子裡面的人,也有很大可能是機械系花4...
演算法學習之並查集
並查集是一種樹型的結構,常常用來處理一些不相交的集合的合併和查詢問題。查詢 確定元素所在的集合。合併 將兩個集合合併成乙個集合。查詢v所在集合的根節點 int find int v 合併 void merge int x,int y 優化1 int find int x k x while k r ...
演算法學習之 並查集
並查集用於解決連線類問題,判斷網路中節點間的連線狀態。與路徑類問題相比,並查集只回答了節點之間是否連通,而具體的連通路徑並不能確定,因此並查集在某些場景下非常高效。如前所述,此處的並查集實現只提供兩個介面 是否連線,元素合併。下面 使用乙個陣列來記錄每個元素所對應的類別,如果兩個元素的類別相同,則稱...