題解 luogu P3366 【【模板】最小生成樹】
阿新 • • 發佈:2018-12-02
最小生成樹kruskal演算法!
最弱紅名的首道圖論題
貪心演算法,按邊的權值排序,然後看當前指定的兩點有木有已經在一棵樹上,如果有,不管,沒有,merge。然後ans加上那條邊的權值。
#include<bits/stdc++.h> using namespace std; struct path { int k,l,q; }p[200000]; int bcj[200000]; int get(int x) { if (bcj[x]==x)return x; else return bcj[x]=get(bcj[x]); } void merge(int x,int y) { bcj[get(x)]=get(y); }//標準的並查集get和merge void haha(int l,int r) { int i,j,x,y,n; x=p[(l+r)/2].q;i=l;j=r; do{ while(p[i].q<x)i++; while(p[j].q>x)j--; if (i<=j) {swap(p[i].q,p[j].q);swap(p[i].k,p[j].k);swap(p[i].l,p[j].l);i++;j--;} }while(i<=j); if (i<r)haha(i,r); if (j>l)haha(l,j); }//快排 int main() { int i,j,x,y,n,ans=0; cin>>x>>y; for (i=1;i<=x;i++)bcj[i]=i;//初始化並查集 for (i=1;i<=y;i++) { int k,l; cin>>p[i].k>>p[i].l>>p[i].q; }//讀入邊 haha(1,y); for (i=1;i<=y;i++) if (get(p[i].k)!=get(p[i].l)){merge(p[i].k,p[i].l);ans+=p[i].q;};//如果不在同樹上就合併 for (i=1;i<=x;i++) { if (get(i)!=get(1)){cout<<"orz";return 0;} }//如果有多個樹根,輸出orz cout<<ans; return 0; }
the end