AtCoder - 2568 Lotus Leaves

Problem Statement

There is a pond with a rectangular shape. The pond is divided into a grid with H rows and W columns of squares. We will denote the square at the i-th row from the top and j-th column from the left by (ij).

Some of the squares in the pond contains a lotus leaf floating on the water. On one of those leaves, S, there is a frog trying to get to another leaf T. The state of square (ij) is given to you by a character aij, as follows:

  • . : A square without a leaf.
  • o : A square with a leaf floating on the water.
  • S : A square with the leaf S.
  • T : A square with the leaf T.

The frog will repeatedly perform the following action to get to the leaf T: "jump to a leaf that is in the same row or the same column as the leaf where the frog is currently located."

Snuke is trying to remove some of the leaves, other than S and T, so that the frog cannot get to the leaf T. Determine whether this objective is achievable. If it is achievable, find the minimum necessary number of leaves to remove.

Constraints
  • 2H,W100
  • aij is ., o, S or T.
  • There is exactly one S among aij.
  • There is exactly one T among aij.
Input

Input is given from Standard Input in the following format:

H W
a11  a1W
:
aH1  aHW
Output

If the objective is achievable, print the minimum necessary number of leaves to remove. Otherwise, print -1 instead.

Sample Input 1
3 3
S.o
.o.
o.T
Sample Output 1
2

Remove the upper-right and lower-left leaves.

Sample Input 2
3 4
S...
.oo.
...T
Sample Output 2
0
Sample Input 3
4 3
.S.
.o.
.o.
.T.
Sample Output 3
-1
Sample Input 4
10 10
.o...o..o.
....o.....
....oo.oo.
..oooo..o.
....oo....
..o..o....
o..o....So
o....T....
....o.....
........oo
Sample Output 4
5


非常神奇的二分图建模!
我们把行和列分别看成二分图两边的一排节点,那么我们的任务其实就是找到一个最小割,使得从S 的行或列 走不到 T的行或列。
所以对于原图中的一片荷叶(i,j) ,我们就在二分图中添加 无向边 行i to 列j,再连 S 到 S行,S列 ; T行,T列到T。容量都是inf。

这样原图中的最小割就是答案了,如果答案>=inf那么无解,说明S,T在同一行或者同一列。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
#define ll long long
using namespace std;
const int maxn=305,inf=1e8;
#define pb push_back
struct lines{
	int to,flow,cap;
}l[maxn*maxn*5];
vector<int> g[maxn];
int cur[maxn],d[maxn],t=-1,S,T;
bool v[maxn];

inline void add(int from,int to,int cap){
	l[++t]=(lines){to,0,cap},g[from].pb(t);
	l[++t]=(lines){from,0,0},g[to].pb(t);
}

inline bool BFS(){
	memset(v,0,sizeof(v)),v[S]=1,d[S]=0;
	queue<int> q; q.push(S);
	int x; lines e;
	
	while(!q.empty()){
		x=q.front(),q.pop();
		for(int i=g[x].size()-1;i>=0;i--){
			e=l[g[x][i]];
			if(e.flow<e.cap&&!v[e.to]) v[e.to]=1,d[e.to]=d[x]+1,q.push(e.to);
		}
	}
	
	return v[T];
}

int dfs(int x,int A){
	if(x==T||!A) return A;
	int flow=0,f,sz=g[x].size();
	for(int &i=cur[x];i<sz;i++){
		lines &e=l[g[x][i]];
		if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(e.cap-e.flow,A)))){
			A-=f,flow+=f;
			e.flow+=f,l[g[x][i]^1].flow-=f;
			if(!A) break;
		}
	}
	
	return flow;
}

inline int max_flow(){
	int an=0;
	while(BFS()){
		memset(cur,0,sizeof(cur));
		an+=dfs(S,inf);
	}
	return an;
}

int n,m;
char ch;

int main(){
	scanf("%d%d",&n,&m),S=0,T=n+m+1;
	for(int i=1;i<=n;i++)
	    for(int j=1;j<=m;j++){
	    	ch=getchar();
	    	while(ch!='.'&&ch!='o'&&ch!='S'&&ch!='T') ch=getchar();
	    	if(ch!='.') add(i,j+n,1),add(j+n,i,1);
	    	if(ch=='S') add(S,i,inf),add(S,j+n,inf);
	    	else if(ch=='T') add(i,T,inf),add(j+n,T,inf);
		}
	
	int ans=max_flow();
	if(ans>=inf) puts("-1");
	else printf("%d\n",ans);
	
	return 0;
}
 

猜你喜欢

转载自www.cnblogs.com/JYYHH/p/9101178.html