【BZOJ4950】lydsy七月月赛 C
题解:比较直接的想法就是:每行,每列的最大值都留下,剩下的格子都变成1。但是如果一个格子既是行的最大值又是列的最大值,那么我们只需要把它留下即可。这就变成了一个二分图最大匹配问题,乱搞即可。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long ll; int n,m,cnt,now; ll ans; ll map[110][110],s1[110],s2[110]; int to[10010],next[10010],head[110],vis[110],from[110]; void add(int a,int b) { to[++cnt]=b,next[cnt]=head[a],head[a]=cnt; } int dfs(int x) { for(int i=head[x];i;i=next[i]) { if(vis[to[i]]) continue; vis[to[i]]=1; if(!from[to[i]]||dfs(from[to[i]])) { from[to[i]]=x; return 1; } } return 0; } int main() { scanf("%d%d",&n,&m); int i,j; for(i=1;i<=n;i++) for(j=1;j<=m;j++) scanf("%lld",&map[i][j]),s1[i]=max(s1[i],map[i][j]),s2[j]=max(s2[j],map[i][j]),ans+=map[i][j]; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { if(map[i][j]) { ans--; if(s1[i]>1&&s1[i]==s2[j]) add(i,j); } } for(i=1;i<=n;i++) if(s1[i]) ans-=s1[i]-1; for(i=1;i<=m;i++) if(s2[i]) ans-=s2[i]-1; for(i=1;i<=n;i++) if(s1[i]) memset(vis,0,sizeof(vis)),ans+=dfs(i)*(s1[i]-1); printf("%lld",ans); return 0; }