F - Lotus Leaves
Time limit : 2sec / Memory limit : 256MB
Score : 800 points
Problem Statement
There is a pond with a rectangular shape. The pond is divided into a grid withH rows andW columns of squares. We will denote the square at thei-th row from the top andj-th column from the left by(i, j).
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 leafT. The state of square(i, j) 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 leafT. Determine whether this objective is achievable. If it is achievable, find the minimum necessary number of leaves to remove.
Constraints
- 2≤H,W≤100
- aij is
.
,o
,S
orT
. - 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
题解:
考虑最小割模型。把每行、每列建成点,加上源点和汇点,一共H+W+2个点。源点向字符S所在的行和列连流量为无穷大的边,T所在的行和列向汇点连流量为无穷大的边,字符o所在的行列之间连流量为1的双向边,割掉其中的一条边表示去掉这个o。最后如果流量为无穷大则输出-1。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf=30000;
int edge[30000],nxt[30000],flow[30000],first[300];
int g[300],h[300];
char c[300][300];
int i,j,m,n,s,head,tail,sum_edge;
inline void addedge(int x,int y,int f)
{
sum_edge++,edge[sum_edge]=y,flow[sum_edge]=f,nxt[sum_edge]=first[x],first[x]=sum_edge;
return;
}
inline int oppedge(int x)
{
return ((x-1)^1)+1;
}
inline void buildgraph()
{
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++)
scanf("%s",c[i]+1);
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
switch (c[i][j])
{
case 'S':
addedge(0,i,inf),addedge(i,0,0);
addedge(0,n+j,inf),addedge(n+j,0,0);
break;
case 'T':
addedge(i,n+m+1,inf),addedge(n+m+1,i,0);
addedge(n+j,n+m+1,inf),addedge(n+m+1,n+j,0);
break;
case 'o':
addedge(i,n+j,1),addedge(n+j,i,1);
break;
}
return;
}
inline int dinic_bfs()
{
memset(h,0,sizeof(h));
tail=1,g[tail]=0,h[g[tail]]=1;
for (head=1;head<=tail;head++)
for (i=first[g[head]];i!=0;i=nxt[i])
if ((flow[i]) && (! h[edge[i]]))
tail++,g[tail]=edge[i],h[g[tail]]=h[g[head]]+1;
return h[n+m+1];
}
inline int dinic_dfs(int now,int cap)
{
if (now==n+m+1)
return cap;
int s=0,t=0;
for (int i=first[now];i!=0;i=nxt[i])
if ((flow[i]) && (h[edge[i]]==h[now]+1))
{
t=dinic_dfs(edge[i],min(cap,flow[i]));
s=s+t,cap=cap-t;
flow[i]=flow[i]-t,flow[oppedge(i)]=flow[oppedge(i)]+t;
if (! cap)
break;
}
if (cap)
h[now]=0;
return s;
}
inline void maxflow()
{
while (dinic_bfs())
s=s+dinic_dfs(0,inf);
if (s>n*m)
printf("-1");
else
printf("%d",s);
return;
}
int main()
{
buildgraph();
maxflow();
return 0;
}