题目分享J 二代目
Posted lin4xu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题目分享J 二代目相关的知识,希望对你有一定的参考价值。
题意:给一个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(" "); for(int i=1;i<=n;i++) { printf("%d",wy[i]); if(i!=n) printf(" "); ans+=wy[i]; } printf(" "); 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 ",km()); } return 0; }
以上是关于题目分享J 二代目的主要内容,如果未能解决你的问题,请参考以下文章