本文版權歸ljh2000和博客園共有,歡迎轉載,但須保留此聲明,並給出原文連接,謝謝合做。php
本文做者:ljh2000
做者博客:http://www.cnblogs.com/ljh2000-jump/
轉載請註明出處,侵權必究,保留最終解釋權!ios
題目連接:BZOJ4883spa
正解:貪心blog
解題報告:get
又是用貪心模擬費用流…博客
考慮直接跑費用流,複雜度很不靠譜,那麼用以前$get$的姿式:用貪心模擬費用流。string
費用流建圖的話很是$simple$,若是咱們用相似最小生成樹的方式,把邊按邊權從小到大往裏面加。it
咱們觀察一下費用流建的那張圖,一次增廣,本質上能夠當作是選擇了一個行編號和一個列編號,那麼咱們考慮每一個點加入時的狀況。至關因而每一個行、列所表明的點的入度強制要爲1,那麼只有多是帶一個環的樹;若是圖是一棵樹,那麼必然能夠匹配;若是是一棵n條邊的基環樹,那麼也能匹配。分類討論,除非兩個都爲圖,不然就能匹配。按最小生成樹的方式作就行了。io
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦關終屬楚;苦心人,天不負,臥薪嚐膽,三千越甲可吞吳。 #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cstdio> #include <string> #include <queue> #include <cmath> #include <ctime> #define lc root<<1 #define rc root<<1|1 #define reg(i,x) for(int i=first[x];i;i=nxt[i]) using namespace std; typedef long long LL; const int MAXN = 200011; int n,m,cnt,fa[MAXN]; bool G[MAXN]; LL ans; struct edge{ int x,y,z; }e[MAXN]; inline bool cmp(edge q,edge qq){ return q.z<qq.z; } inline int find(int x){ if(fa[x]!=x) fa[x]=find(fa[x]); return fa[x]; } inline void link(int x,int y,int z){ e[++cnt].x=x; e[cnt].y=y; e[cnt].z=z; } inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } inline void work(){ n=getint(); m=getint(); int x,y,z; for(int i=n+m;i>=1;i--) fa[i]=i; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { z=getint(); link(i,j+n,z); } sort(e+1,e+cnt+1,cmp); for(int i=1;i<=cnt;i++) { x=find(e[i].x); y=find(e[i].y); if(G[x] && G[y]) continue; if(x!=y){ fa[x]=y; G[y]|=G[x]; } else G[y]=1; ans+=e[i].z; } printf("%lld",ans); } int main() { #ifndef ONLINE_JUDGE freopen("4883.in","r",stdin); freopen("4883.out","w",stdout); #endif work(); return 0; } //有志者,事竟成,破釜沉舟,百二秦關終屬楚;苦心人,天不負,臥薪嚐膽,三千越甲可吞吳。