C++ P3366 【模板】最小生成樹 --- kruskal
阿新 • • 發佈:2018-11-10
Kruskal的用處:
- 得出一個圖的一個最小生成樹(最小生成樹就是一個圖中總權值最小的一個子樹)
Kruskal的思想:
- 由於要獲得最小生成樹,而最小生成樹一定連線了所有結點,所以邊權最小的邊一定會被選擇(這個需要自己證明)
- 然後,我們將邊權最小的邊進行縮點,縮點的方法是使用並查集,也就是把互相連線的點放到同一個集合。
- 然後重複第一個步驟。當已選擇的邊的數量等於點的總數減一時,則最小生成樹已建立完成。
Kruskal的具體實現:
- 獲取邊權最小的邊可以使用sort函式,也可以使用優先佇列
- 縮點可以使用並查集
例題: https://www.luogu.org/problemnew/show/P3366
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; int ans=0,cnt=0,n,m,fa[200005]; struct Edge{ int u,v,w; }e[200005]; int cmp(Edge a,Edge b){ return a.w<b.w; } void addEdge(int u,int v,int w){ e[++cnt].u=u; e[cnt].v=v; e[cnt].w=w; } int find(int a){ while(a!=fa[a]){ a=fa[a]=fa[fa[a]]; } return a; } void kruskal(){ int eu,ev; int sum=0; for(int i=1;i<=m;i++){ eu=find(e[i].u),ev=find(e[i].v); if(eu==ev)continue; sum++; fa[eu]=ev; ans+=e[i].w; if(sum==n-1)return; } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ fa[i]=i; } for(int i=1;i<=m;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); addEdge(a,b,c); } sort(e,e+m,cmp); kruskal(); printf("%d\n",ans); return 0; }
歡迎加入我們的OI討論群
群號:849352599