1. 程式人生 > >kruskal:最小生成樹

kruskal:最小生成樹

pac 循環 space print https clas 沒有 lan +=

luogu P3366 【模板】最小生成樹

在連接各個點的所有路徑中,選取最短的路徑連接所有點

n個頂點,e條邊,時間復雜度O(eloge)

kruskal主要思路:

  1. 輸入邊,用結構體儲存

  2. 用結構體快排以邊比較從小到大快排

  3. 建一個並查集,並初始化並查集(並查集代表兩個點有沒有在同一個樹裏面

  4. for(i=1;i<=m(邊數);i++)找一條邊,若其連接的兩個點不在同一個並查集裏面,就將兩者所在的並查集合並,並將ans+=s[i].len。

  5. 若在同一個並查集,則跳過這次循環。因為如果這兩個點連接起來,就會形成一個環。

  6. 直到邊有n-1條

#include<cstdio>
#include
<cstring> #include<algorithm> using namespace std; struct ll { int x,y,len; }s[200020]; bool cmp(ll a,ll b) { return a.len<b.len; } int n,m,ans; int fa[5050],big[5050]; int getfa(int x) { if(fa[x]==x) return x; return fa[x]=getfa(fa[x]); } void gaibaba(int x,int y) { int ba1=getfa(x),ba2=getfa(y);
if(ba1==ba2) return; if(big[ba1]<big[ba2]) { fa[ba1]=ba2; big[ba2]+=big[ba1]; } else { fa[ba2]=ba1; big[ba1]+=big[ba2]; } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].len); fa[s[i].x]
=s[i].x; fa[s[i].y]=s[i].y; } int k=0; sort(s+1,s+m+1,cmp); for(int i=1;i<=m;i++) { if(getfa(s[i].x)!=getfa(s[i].y)) { ans+=s[i].len; gaibaba(s[i].x,s[i].y ); k++; } if(k==n-1) { printf("%d",ans); return 0; } } printf("orz"); return 0; }

kruskal:最小生成樹