Bzoj 4950 (二分图最大匹配)

Posted NINGLONG

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj 4950 (二分图最大匹配)相关的知识,希望对你有一定的参考价值。

Description

那是春日里一个天气晴朗的好日子,你准备去见见你的老朋友Patrick,也是你之前的犯罪同伙。Patrick在编程竞赛
上豪赌输掉了一大笔钱,所以他需要再干一票。为此他需要你的帮助,虽然你已经金盆洗手了。你刚开始很不情愿,
因为你一点也不想再回到那条老路上了,但是你觉得听一下他的计划也无伤大雅。在附近的一个仓库里有一批货物,
包含一些贵重的消费性部件,Patrick企图从中尽可能多地偷些东西出来。这意味着要找一条进去的路,弄晕安保人
员,穿过各种各样的激光射线,你懂的,都是常见的抢劫技术。然而,仓库的核心装备了一套Patrick搞不定的安保系
统。这也是他需要你帮助他的地方。这批货物被放置在一些巨大的立方体箱里,每个箱子的尺寸都是相同的。这些
箱子堆放成许多整齐的堆,每个箱子可以表示成一个三维的网格。安保系统每个小时会用三台相机对这堆货物进行
一次拍照,相机分别为:前置相机(front camera),侧置相机(side camera)和顶置相机(top camera)。前置相机的照
片显示了每一行最高的那堆箱子的高度,侧置相机显示了每一列最高的那堆箱子的高度,顶置相机显示了每个位置是
否存在一堆箱子。如果安保系统发现任何一张照片出现了变化,它会立即拉响警报。一旦 Patrick 进去了,他会确
定每堆箱子的高度并且发给你。图1显示了一种网格可能的放置,以及每台相机会得到的视图。
技术分享
图 1. 网格的高度值与对应的相机视图。
技术分享
图 2. 洗劫后网格可能的高度值。
 
Patrick想尽可能多偷走一些箱子。由于他不能弄坏安保系统,他准备重新安排剩余每堆箱子的放置,使得下一次相
机取像时会得到相同的照片,从而骗过安保系统。在上面的例子中,他可以偷走九个箱子。图2显示了一种可能的剩
余箱子的安置方案能使得安保系统认为与原安置情况相同。Patrick想请你帮他确定在保证能骗过安保系统的情况
下他最多能偷走多少个箱子。你会帮他干完这最后一票么?

Input

第一行包含两个整数r(1≤r≤100)和c(1≤n≤100),分别表示网格的行数与列数。
接下来r行,每行包含c个整数,表示对应行上每堆立方体箱的高度(箱子的数量)。
所有的高度在0到10^9之间 (含边界) 。

Output

输出在不被发现的情况下最多能偷走多少箱子。

Sample Input

样例1
5 5
1 4 0 5 2
2 1 2 0 1
0 2 3 4 4
0 3 0 3 1
1 2 2 1 1
样例2
2 3
50 20 3
20 10 3

Sample Output

样例1
9
样例2
30
 
---------------------------------------------------------------------
题解:
  对于俯视图,我们使有箱子的格子不被拿完即可。对于侧视图和正视图,使行和列的最大值保持不变即可。
  注意到某一行和某一列的最大值可能相同,对此,我们将尽量保留这样的最大值。
  将最大值相等的行和列连边,跑一遍二分图最大匹配即可。
 
 
 1 #include<stdio.h> 
 2 #include<string.h> 
 3 #include<algorithm> 
 4 using namespace std; 
 5 #define MAXN 100000+10 
 6 typedef long long LL; 
 7 struct ed{LL v,next;}edge[MAXN]; 
 8 LL match[220],head[220],vis[220],n,m; 
 9 LL map[220][220],sum=0,mh[220],ml[220]; 
10 void add(LL u,LL v){ 
11     static LL tot=0; 
12     edge[++tot].v=v; 
13     edge[tot].next=head[u]; 
14     head[u]=tot; 
15 } 
16 bool dfs(LL u){ 
17     for(LL i=head[u];i;i=edge[i].next){ 
18         LL v=edge[i].v; 
19         if(vis[v])continue; 
20         vis[v]=1; 
21         if(!match[v]||dfs(match[v])){ 
22             match[v]=u; 
23             return true; 
24         } 
25     } 
26     return false; 
27 } 
28 int main(){ 
29     scanf("%lld%lld",&n,&m); 
30     for(LL i=1;i<=n;i++) 
31         for(LL j=1;j<=m;j++){ 
32             scanf("%lld",&map[i][j]); 
33             mh[i]=max(mh[i],map[i][j]); 
34             ml[j]=max(ml[j],map[i][j]); 
35             if(map[i][j])sum+=map[i][j]-1; 
36         } 
37     for(LL i=1;i<=n;i++) 
38         for(LL j=1;j<=m;j++) 
39             if(mh[i]&&map[i][j]&&mh[i]==ml[j])add(i,n+j); 
40     for(LL i=1;i<=n;i++)if(mh[i])sum-=mh[i]-1; 
41     for(LL i=1;i<=m;i++)if(ml[i])sum-=ml[i]-1; 
42     for(LL i=1;i<=n;i++){ 
43         memset(vis,0,sizeof(vis)); 
44         if(mh[i]&&dfs(i))sum+=mh[i]-1; 
45     } 
46     printf("%lld",sum); 
47     return 0; 
48 }

 

  













以上是关于Bzoj 4950 (二分图最大匹配)的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj 4950 (二分图最大匹配)

bzoj-1854(二分图最大匹配)

bzoj 1854: [Scoi2010]游戏 (并查集||二分图最大匹配)

bzoj 1059: [ZJOI2007]矩阵游戏 [二分图][二分图最大匹配]

bzoj-1191(二分图最大匹配)

BZOJ 4808 二分图最大独立集