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

来源:互联网 发布:阿里云幕布可以ps吗 编辑:程序博客网 时间:2024/04/26 23:15

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

#include <bits/stdc++.h>using namespace std;#define N 110#define ll long long#define inf 0x3f3f3f3f#define eps 1e-9inline int read(){    int x=0,f=1;char ch=getchar();    while(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[N][N],mxn[N],mxm[N],boy[N];ll ans=0;bool f[N];vector<int>e[N];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;}
原创粉丝点击