#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define re return #define ll long long #define inc(i,l,r) for(int i=l;i<=r;++i) const int inf=2147483647,maxn=305; using namespace std; template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<‘0‘||c>‘9‘)if(c==‘-‘)f=1; x=c^48; while((c=getchar())>=‘0‘&&c<=‘9‘)x=x*10+(c^48); if(f)x=-x; } int n; int ex1[maxn];//1的期望度 int ex2[maxn];//2的期望度 int pri[maxn][maxn];//价格 int match[maxn];//匹配2的1 int vis1[maxn];//1是否被访问过 int vis2[maxn];//2是否访问过 int slack[maxn];//最小差多少,2可以被1访问 inline bool dfs(int x) { vis1[x]=1;//标记1访问 inc(i,1,n) { if(vis2[i])continue; if(ex1[x]+ex2[i]==pri[x][i])//达到访问要求 { vis2[i]=1;标记2访问 if(!match[i]||dfs(match[i])) { match[i]=x; re 1; } } else slack[i]=min(slack[i],ex1[x]+ex2[i]-pri[x][i]); //2差值统计 } re 0; } inline void KM() { inc(i,1,n)match[i]=ex2[i]=0; //刷新 inc(i,1,n) { inc(j,1,n) slack[j]=inf; while(2333) { inc(j,1,n)vis1[j]=vis2[j]=0; if(dfs(i))break; int d=inf; inc(j,1,n) if(!vis2[j]) d=min(d,slack[j]); //最小改变度 inc(j,1,n) { if(vis1[j])ex1[j]-=d; if(vis2[j])ex2[j]+=d; else slack[j]-=d; //分别改变 } } } } int main() { while(~scanf("%d",&n)) { inc(i,1,n)ex1[i]=-inf; inc(i,1,n) inc(j,1,n) { rd(pri[i][j]); ex1[i]=max(ex1[i],pri[i][j]); } int ans=0; KM(); for(int i=1;i<=n;++i) ans+=pri[match[i]][i]; printf("%d\n",ans); } re 0; }
原文:https://www.cnblogs.com/lsyyy/p/11366195.html