[Tjoi2016&Heoi2016]游戏 二分图最大匹配

来源:互联网 发布:查淘宝买家退货率 编辑:程序博客网 时间:2024/05/24 01:45

4554: [Tjoi2016&Heoi2016]游戏

Time Limit: 20 Sec  Memory Limit: 128 MB
[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


行列连边,然而蜜汁网络流挂了

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#define INF 0x7fffffffusing namespace std;const int N = 4005;int last[N],h[N],q[N],S,T,n,m,cnt=1,cur[N],ans,x[55][55],y[55][55],nx=0,ny=0,vst[N],f[N];char a[55][55];struct Edge{int to,next,v;}e[N*40];void insert( int u, int v, int w ){e[++cnt].to = v; e[cnt].next = last[u]; e[cnt].v = w; last[u] = cnt;e[++cnt].to = u; e[cnt].next = last[v]; e[cnt].v = 0; last[v] = cnt;}bool bfs(){memset(h,-1,sizeof(h));int tail = 1, head = 0;q[0] = S; h[S] = 0;while( tail != head ){int now = q[head++];for( int i = last[now]; i; i = e[i].next )if( h[e[i].to] == -1 && e[i].v ){h[e[i].to] = h[now] + 1;q[tail++] = e[i].to;}}return h[T] != -1;}int dfs1( int x, int f ){int w,used=0;if( x == T ) return f;for( int i = cur[x]; i; i = e[i].next )if( h[e[i].to] == h[x] + 1 ){w = dfs1(e[i].to,min(e[i].v,f-used));e[i].v -= w; e[i^1].v += w; used += w;if( e[i].v ) cur[x] = i; if( f == used ) return f;}if( !used ) h[x] = -1;return used;}void dinic(){while( bfs() ){for( int i = 0; i <= T; i++ ) cur[i] = last[i];ans += dfs1(S,INF);}}bool dfs(int x){for(int i=last[x];i;i=e[i].next){int y=e[i].to;if (vst[y]) continue;vst[y]=1;if (!f[y]||dfs(f[y])){f[y]=x;return true;}}return false;}int main(){scanf("%d%d", &n, &m);for( int i = 1; i <= n; i++ ) scanf("%s", a[i]+1);for( int i = 1; i <= n; i++ )for( int j = 1; j <= m; j++ )x[i][j] = ( j == 1 || a[i][j] == '#' ) ? ++nx : nx;ny = nx;for( int j = 1; j <= m; j++ )for( int i = 1; i <= n; i++ )y[i][j] = ( i == 1 || a[i][j] == '#' ) ? ++ny : ny;T = ny+nx+2; S = ny+nx+1;for( int i = 1; i <= n; i++ )for( int j = 1; j <= m; j++ )if( a[i][j] == '*')insert(x[i][j],y[i][j],1);/*for( int i = 1; i <= nx; i++ ) insert( S, nx, 1 );for( int i = 1; i <= ny; i++ ) insert( ny, T, 1 );dinic();*/for( int i = 1; i <= nx; i++ ){memset(vst,0,sizeof(vst));if (dfs(i)) ans++;}printf("%d", ans);return 0;}


阅读全文
0 0
原创粉丝点击