圖論之kruskal
阿新 • • 發佈:2018-12-14
最近新學了一個生成樹演算法,kruskal。
先給出一道純模板題
傳送門:http://codevs.cn/problem/1078/大意:給你一些邊,你選一些邊將所有點連成連通圖,並且這些邊的權值和最小,輸出這個最小權值
思路:
首先我們知道,當我們選一些邊所建的連通圖為一個樹時,圖中的邊數最少,也意味著我們所需的權值的個數最少,如果再能保證這些邊的權值很小,那麼我們的目的就完成了。
而完成上述思路,就需用到kruskal演算法。
kruskal演算法基於貪心思路,我們先把這些邊依據輸入順序,開一個結構體存進去。然後將整個結構體依據權值關鍵字升序排序。
然後從權值最小的邊開始,用並查集的方法,每一條邊,查詢他的根節點是否同一,若同一,證明他們已在同一棵樹上,及它們之間已經聯通,不需要再浪費一條邊;而若不同一,則把起點的祖先的祖先設為終點的祖先,那麼他們就連通了。這就是思路
程式碼如下:
#include<stdio.h> #include<algorithm> using namespace std; struct edge{ int u,v,w; }a[10100]; int tot=0,fa[10100]; bool cmp(edge a,edge b) { return a.w<b.w; } int find(int num) { if(fa[num]==num)return num; return fa[num]=find(fa[num]); } int main() { int ans=0,n,m=0; scanf("%d",&n); --tot; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { int z; scanf("%d",&z); if(i<j) { a[++tot].u=i; a[tot].v=j; a[tot].w=z; } } fa[i]=i; } sort(a,a+1+tot,cmp); for(int i=0;i<=tot&&m<n;i++) { int x=find(a[i].u),y=find(a[i].v),z=a[i].w; if(x==y)continue; fa[x]=a[i].v; ans+=z; m++; } printf("%d",ans); return 0; }