1. 程式人生 > >Bzoj 4950 (二分圖最大匹配)

Bzoj 4950 (二分圖最大匹配)

void ide 機會 出現 geo front 老朋友 放置 scrip

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 (二分圖最大匹配)