1. 程式人生 > >二分圖 BZOJ4554 [Tjoi2016&Heoi2016]遊戲

二分圖 BZOJ4554 [Tjoi2016&Heoi2016]遊戲

bbs ret www href sca logs scu bmi ring

4554: [Tjoi2016&Heoi2016]遊戲

Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 579 Solved: 350
[Submit][Status][Discuss]

Description

在2016年,佳緣姐姐喜歡上了一款遊戲,叫做泡泡堂。簡單的說,這個遊戲就是在一張地圖上放上若幹個炸彈,看 是否能炸到對手,或者躲開對手的炸彈。在玩遊戲的過程中,小H想到了這樣一個問題:當給定一張地圖,在這張 地圖上最多能放上多少個炸彈能使得任意兩個炸彈之間不會互相炸到。炸彈能炸到的範圍是該炸彈所在的一行和一 列,炸彈的威力可以穿透軟石頭,但是不能穿透硬石頭。給定一張n*m的網格地圖:其中*代表空地,炸彈的威力可 以穿透,可以在空地上放置一枚炸彈。x代表軟石頭,炸彈的威力可以穿透,不能在此放置炸彈。#代表硬石頭,炸 彈的威力是不能穿透的,不能在此放置炸彈。例如:給出1*4的網格地圖*xx*,這個地圖上最多只能放置一個炸彈 。給出另一個1*4的網格地圖*x#*,這個地圖最多能放置兩個炸彈。現在小H任意給出一張n*m的網格地圖,問你最 多能放置多少炸彈

Input

第一行輸入兩個正整數n,m,n表示地圖的行數,m表示地圖的列數。1≤n,m≤50。接下來輸入n行m列個字符,代表網 格地圖。*的個數不超過n*m個

Output

輸出一個整數a,表示最多能放置炸彈的個數

Sample Input

```
4 4
#***
*#**
**#*
xxx#
```

Sample Output

5

HINT

Source

拆“#”,變為典型題

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5
using namespace std; 6 int n,m,cnt,ans,xx,yy; 7 int fa[3010],head[3010],xxx[3010][3010],yyy[3010][3010]; 8 bool check[3010]; 9 char s[60][60]; 10 struct data{ 11 int next,to; 12 }edge[3010]; 13 void add(int start,int end){ 14 edge[++cnt].next=head[start]; 15 edge[cnt].to=end; 16 head[start]=cnt; 17
} 18 bool dfs(int x){ 19 for(int i=head[x];i;i=edge[i].next) 20 if(!check[edge[i].to]){ 21 check[edge[i].to]=1; 22 if(!fa[edge[i].to]||dfs(fa[edge[i].to])){ 23 fa[edge[i].to]=x; 24 return 1; 25 } 26 } 27 return 0; 28 } 29 void work(){ 30 for(int i=1;i<=xx;i++){ 31 memset(check,0,sizeof(check)); 32 if(dfs(i)) ans++; 33 } 34 printf("%d",ans); 35 } 36 int main(){ 37 scanf("%d%d",&n,&m); 38 for(int i=1;i<=n;i++) scanf("%s",s[i]+1); 39 for(int i=1;i<=n;i++) 40 for(int j=1;j<=m;j++) 41 xxx[i][j]=(j==1||s[i][j]==#)?++xx:xx; 42 for(int j=1;j<=m;j++) 43 for(int i=1;i<=n;i++) 44 yyy[i][j]=(i==1||s[i][j]==#)?++yy:yy; 45 for(int i=1;i<=n;i++) 46 for(int j=1;j<=m;j++) 47 if(s[i][j]==*) add(xxx[i][j],yyy[i][j]); 48 work(); 49 return 0; 50 }

二分圖 BZOJ4554 [Tjoi2016&Heoi2016]遊戲