标签:int next ret 题意 info ems else for 代码
题意:给一个n行n列的矩阵,构造两个数组a,b,使得对于任意x,y≤n满足mapp[x][y]≤a[x]+b[y]
分析:这不就是个KM算法的板子题吗?
(摘自老姚博客)
所以只需要输出A数组B数组与ans即可(真没啥好说的,我称之为KM算法附赠品)
代码:
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1e3+1; const int maxm=1e6+1; const int inf=0x3f3f3f3f; struct edge { int to,next; }e[maxm]; int head[maxn]; int g[maxn][maxn]; int wx[maxn]; int wy[maxn]; int match[maxn]; bool visx[maxn]; bool visy[maxn]; int slack[maxn]; int cnt,n; void add(int x,int y) { e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt; } int dfs(int x) { visx[x]=1; for(int i=1;i<=n;i++) { if(!visy[i]) { int now=wx[x]+wy[i]-g[x][i]; if(!now) { visy[i]=1; if(!match[i]||dfs(match[i])) { match[i]=x; return 1; } } else slack[i]=min(slack[i],now); } } return 0; } int km() { memset(match,0,sizeof(match)); memset(wy,0,sizeof(wy)); for(int i=1;i<=n;i++) { memset(slack,0x3f,sizeof(slack)); while(1) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(dfs(i)) break; int minz=inf; for(int j=1;j<=n;j++) if(!visy[j]) minz=min(minz,slack[j]); for(int j=1;j<=n;j++) if(visx[j]) wx[j]-=minz; for(int j=1;j<=n;j++) if(visy[j]) wy[j]+=minz; else slack[j]-=minz; } } int ans=0; for(int i=1;i<=n;i++) { printf("%d",wx[i]); if(i!=n) printf(" "); ans+=wx[i]; } printf("\n"); for(int i=1;i<=n;i++) { printf("%d",wy[i]); if(i!=n) printf(" "); ans+=wy[i]; } printf("\n"); return ans; } int main() { int m,x,y,z; while(scanf("%d",&n)!=EOF) { memset(wx,0,sizeof(wx)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf("%d",&g[i][j]); wx[i]=max(wx[i],g[i][j]); } } printf("%d\n",km()); } return 0; }
标签:int next ret 题意 info ems else for 代码
原文地址:https://www.cnblogs.com/lin4xu/p/12866325.html