【ARC074F】Lotus Leaves 最小割

Description

给你一个n*m网格图,有起点荷叶和终点荷叶,有中转荷叶,其他的格子没东西,一个荷叶可以跳到同一行或者列的另一个荷叶。问最多删掉几个中转荷叶能让起点终点不连通。如果不行输出-1.

Input

​ 第一行是两个正整数R,CR,C

​ 接下来是一个R∗CR∗C的字符矩阵,第ii行第jj个字符为ai,jai,j

​ 若ai,j′.′ai,j′.′,那么这个格子是水面

​ 若ai,j′o′ai,j′o′,那么这个格子是一片荷叶

​ 若ai,j′S′ai,j′S′或者′T′′T′,那么这个格子是标记了S,TS,T的荷叶

Output

​ 如果没有解,那么输出-1

​ 否则输出最少需要删除的个数

Sample Input

Case 1:
3 3
S.o
.o.
o.T

Case 2:
3 4
S...
.oo.
...T

Case 3:
4 3
.S.
.o.
.o.
.T.

Case 4:
10 10
.o...o..o.
....o.....
....oo.oo.
..oooo..o.
....oo....
..o..o....
o..o....So
o....T....
....o.....
........oo

Sample Output

Case 1:
2

Case 2:
0

Case 3:
-1

Case 4:
5

HINT

​ 1≤R,C≤1001≤R,C≤100

​ S,TS,T只出现一次

Sol

考察选手会不会写最大流算法。

对于每行和每列建一个点,然后S向S所在行和列对应的点连inf,T所在的行和列对应的点向T连inf,对于每个荷叶((i,j)),连边(i->j+n,j+n->i),之后跑最大流即可出解。

Code

#include <bits/stdc++.h>
using namespace std;
int n,m,S,T,cnt,inf=1e9,sx,sy,tx,ty,hed[1005],d[1005],nex[50005],to[50005],val[50005],ans;queue<int>q;char ch;
void add(int x,int y,int z)
{
    to[cnt]=y;val[cnt]=z;nex[cnt]=hed[x];hed[x]=cnt++;
    to[cnt]=x;val[cnt]=0;nex[cnt]=hed[y];hed[y]=cnt++;
}
bool bfs()
{
    while(!q.empty()) q.pop();memset(d,0,sizeof(d));d[S]=1;q.push(S);
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=hed[x];i!=-1;i=nex[i]) if(!d[to[i]]&&val[i]){d[to[i]]=d[x]+1;if(to[i]==T) return 1;q.push(to[i]);}
    }
    return 0;
}
int dfs(int x,int mf)
{
    if(x==T) return mf;int tmp=mf;
    for(int i=hed[x];i!=-1;i=nex[i]) if(d[to[i]]==d[x]+1&&val[i])
    {
        int k=dfs(to[i],min(val[i],tmp));
        if(!k) d[to[i]]=0;
        tmp-=k;val[i]-=k;val[i^1]+=k;
        if(!tmp) break;
    }
    return mf-tmp;
}
int main()
{
    scanf("%d%d",&n,&m);T=n+m+1;memset(hed,-1,sizeof(hed));
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
    {
        cin>>ch;
        if(ch=='S') add(S,i,inf),add(S,j+n,inf),sx=i,sy=j;
        if(ch=='T') add(i,T,inf),add(j+n,T,inf),tx=i,ty=j;
        if(ch=='o') add(i,j+n,1),add(j+n,i,1);
    }
    if(sx==tx||sy==ty) return puts("-1"),0;
    while(bfs()) ans+=dfs(0,inf*2);
    printf("%d
",ans);
}
原文地址:https://www.cnblogs.com/CK6100LGEV2/p/9449093.html