並查集,從名字上來看可以知道,是乙個集合,而且這個集合可以合併和查詢。查詢,主要是查詢集合中的某乙個元素的祖先是誰,某一些元素是不是擁有相同的祖先。合併,是把兩個不想交的集合合併為乙個集合。
並查集的思想就是朋友的朋友就是朋友(雖然現實生活中並不是這樣)。
並查集的第一步初始化,自己是自己的祖先。乙個人來到乙個陌生的環境誰也不認識,自己的小團體裡只有自己乙個人。
for (int i=0;i
i++)
pre[i]=i;
然後就是查詢的過程了。慢慢地認識了一些人,自己的團體裡人慢慢變多了,但是你不知道,你這個團體裡的大佬是誰,現在是找到大佬是誰的過程。一共有兩種實現方式,分別是遞迴和迴圈。
pre[ i ] = j ;// i 的祖先是 j
//遞迴實現,先找到自己的頂頭大佬,再找自己頂頭大佬的大佬,,,,
int find_set(int x)
//包含路徑壓縮
int find_set(int x)
//迴圈實現,
int find_set (int x)
//包含路徑壓縮
int find_set (int x)
return r;
}
最後一步合併,把兩個不同的團體合併成乙個團體,讓團體發揚光大。
void merge_set(town a)
}
prim基本思想: 將乙個圖分為兩部分,一部分歸為點集u,一部分歸為點集v,u的初始集合為,v的初始集合為(s為最小生成樹的樹根)。從圖中起點s開始,找與s相關聯且權值最小的邊,並且邊的另乙個頂點b不在集合u裡,把定點b加入集合u內,重複上述過程知道所有的點都加入集合u內。
使用prim演算法圖的結構要存在二維陣列裡(未優化)。時間複雜度為o(v*v)適用於稠密圖
int prim(int s,int n)
}//提前退出,不是連通圖
if (now==inf)
return -1;
v[now]=1,sum+=m;
//更新已加入生成樹點與未加入生成樹點之間的最小權值
for (int j=0; jreturn
sum;
}
kruskal基本思想:將所有邊按從小到大排序,依次判斷邊的兩個頂點是否在同乙個集合,如果不在同乙個集合內,則說明此邊至少其中乙個頂點尚未加入生成樹中或者兩個集合還未聯通,因此將此邊加入生成樹中,重複上述過程知道所有的邊都加入生成樹中。
每條邊的兩個頂點及權值存在結構體裡。時間複雜度o(v*e)。適用於稀疏圖。
#include
#include
#include
#include
using
namespace
std;
const
int max=0x3f3f3f3f;
const
int maxv=1e3+7;
const
int maxe=2e4+7;
int pre[maxv];
int sum,coun;
struct town
edge[maxe];
int cmp(town a,town b)
void merge_set(town a)
}int main()
sort (edge,edge+m,cmp);
sum=coun=0;
for (int i=0; i//加邊的條數少於n-1條說明不能建成最小生成樹
if (coun!=n-1)
printf("-1\n");
else
printf("%d\n",sum);
}return
0;}
並查集(最小生成樹)
時間限制 1000 ms 記憶體限制 65536 kb 題目描述 有一張城市地圖,圖中的頂點為城市,無向邊代表兩個城市間的連通關係,邊上的權為在這兩個城市之間修建高速公路的造價,研究後發現,這個地圖有乙個特點,即任一對城市都是連通的。現在的問題是,要修建若干高速公路把所有城市聯絡起來,問如何設計可使...
最小生成樹 並查集練習
叢林中的路 熱帶島嶼lagrishan的首領現在面臨乙個問題 幾年前,一批外援資金被用於維護村落之間的道路,但日益繁茂的叢林無情的侵蝕著村民的道路,導致道路維修開銷巨大,長老會不得不放棄部分道路的維護。已經知道了每條路每個月的維修費用 單位為aacms 現在長老會需要提出一種方案,即需要保證村落之間...
最小生成樹 kruskal 並查集
題目描述 如題,給出乙個無向圖,求出最小生成樹,如果該圖不連通,則輸出orz 輸入輸出格式 輸入格式 第一行包含兩個整數n m,表示該圖共有n個結點和m條無向邊。n 5000,m 200000 接下來m行每行包含三個整數xi yi zi,表示有一條長度為zi的無向邊連線結點xi yi 輸出格式 輸出...