bzoj 4950(二分图最大匹配)

传送门
题意:求在不改变整个区域的三视图的前提下最多能拿走多少的箱子。
题解:(以下均在俯视的情况下)
对于每个有物品的格子,如果它有k个物品,最多能拿走k-1个。
显然只要留下每行每列最大值即可使三视图不变,于是将减多的补回来。然而这么操作有忽略了一个问题,题目说这个家伙可以重新安排物品位置,所以:如果i行,j列最大值相同,那么将只要交点处摆成最大值,其余的取得只剩1。就是说把多的补回来这一操作又补过了。如何让上述(i行,j列)交点处尽可能放最大值呢,行列建边跑个二分图最大匹配来求最大同时避免冲突(一个最大值只能放一次,即使有一行内两个格子都是最大值也只留一个,因为题目说要尽可能拿走!)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=104;
int n,m;
bool vis[MAXN<<1];
int mat[MAXN<<1];
int a[MAXN][MAXN],r[MAXN],c[MAXN];
int head[MAXN<<1],etot=0;
struct EDGE {
    int v,nxt;
}e[MAXN*MAXN<<2];
inline void adde(int u,int v) {
    e[etot].nxt=head[u],e[etot].v=v,head[u]=etot++;
    e[etot].nxt=head[v],e[etot].v=u,head[v]=etot++;
}
bool dfs(int p) {
    for (int i=head[p];~i;i=e[i].nxt) {
        int v=e[i].v;
        if (!vis[v]) {
            vis[v]=true;
            if (mat[v]==-1||dfs(mat[v])) {
                mat[v]=p;
                return true;
            }
        }
    }
    return false;
}
int main() {
//  freopen("bzoj 4950.in","r",stdin);
    memset(head,-1,sizeof(head));
    memset(mat,-1,sizeof(mat));
    scanf("%d%d",&n,&m);
    ll sum=0;
    for (int i=1;i<=n;++i)
        for (int j=1;j<=m;++j) {
            scanf("%d",&a[i][j]);
            r[i]=max(r[i],a[i][j]);
            c[j]=max(c[j],a[i][j]);
            if (a[i][j]) sum+=a[i][j]-1;
        }
    for (int i=1;i<=n;++i)
        if (r[i]) sum-=r[i]-1;
    for (int j=1;j<=m;++j)
        if (c[j]) sum-=c[j]-1;
    for (int i=1;i<=n;++i)
        for (int j=1;j<=m;++j)
            if (r[i]&&a[i][j]&&r[i]==c[j])
                adde(i,j+n);
    for (int i=1;i<=n;++i) {
        memset(vis,false,sizeof(vis));
        if (r[i]) sum+=dfs(i)*(r[i]-1);
    }
    printf("%lld\n",sum);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值