您的位置:首页 > 其它

bzoj4950 [Wf2017]Mission Improbable(二分图最大匹配)

2017-10-02 12:31 441 查看
一开始考虑,每个不为0的位置都拿到1,然后每行每列最大值不能动。然后又考虑到,如果行列最大值相同,我们可以在他们交叉的位置放一个最大值即可,而不需要两个。因此转化成一个二分图匹配的问题。(显然不同的最大值不会互相干扰,因为之间根本不可能有边)每成功匹配到一个,就可以多拿一个最大值。

#include <bits/stdc++.h>
using namespace std;
#define N 110
#define ll long long
#define inf 0x3f3f3f3f
#define eps 1e-9
inline int read(){
int x=0,f=1;char ch=getchar();
while<
4000
/span>(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,m,a

,mxn
,mxm
,boy
;
ll ans=0;
bool f
;
vector<int>e
;
bool find(int x){
for(int i=0;i<e[x].size();++i){
int y=e[x][i];if(f[y]) continue;
f[y]=1;if(!boy[y]||find(boy[y])){
boy[y]=x;return 1;
}
}return 0;
}
int main(){
//  freopen("a.in","r",stdin);
n=read();m=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
a[i][j]=read();if(a[i][j]) ans+=a[i][j]-1;
mxn[i]=max(mxn[i],a[i][j]);mxm[j]=max(mxm[j],a[i][j]);
}
for(int i=1;i<=n;++i) if(mxn[i]) ans-=mxn[i]-1;//每行最大值不能拿走
for(int j=1;j<=m;++j) if(mxm[j]) ans-=mxm[j]-1;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)//行列最大相同,建边。
if(mxn[i]==mxm[j]&&a[i][j]) e[i].push_back(j);
for(int i=1;i<=n;++i){
memset(f,0,sizeof(f));if(find(i)) ans+=mxn[i]-1;//可以匹配,建一个就好了
}
printf("%lld\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: