kruskal:最小生成樹
阿新 • • 發佈:2019-01-21
pac 循環 space print https clas 沒有 lan +=
luogu P3366 【模板】最小生成樹
在連接各個點的所有路徑中,選取最短的路徑連接所有點
n個頂點,e條邊,時間復雜度O(eloge)
kruskal主要思路:
-
輸入邊,用結構體儲存
-
用結構體快排以邊比較從小到大快排
-
建一個並查集,並初始化並查集(並查集代表兩個點有沒有在同一個樹裏面
-
for(i=1;i<=m(邊數);i++)找一條邊,若其連接的兩個點不在同一個並查集裏面,就將兩者所在的並查集合並,並將ans+=s[i].len。
-
若在同一個並查集,則跳過這次循環。因為如果這兩個點連接起來,就會形成一個環。
- 直到邊有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:最小生成樹