您的位置:首页 > 其它

Atcoder Regular Contest 074 F Lotus Leaves

2018-02-27 16:19 656 查看

Lotus Leaves

Problem Statement

给出一个H*W 的矩阵,矩阵上有很多水池,有一个水池是起点,一个是终点,从起点出发,每次可以跳到同一行或同一列的水池,问至少要删掉多少个水池才能无法到达终点,若无论如何都会到达终点,则输出−1。

Data Constraint

2≤H,W ≤100

Solution

建立网络流模型,把每一个水池视为一条容量为1的边,连接该水池所在行和列。

求最小割就是求删掉水池的最小个数。

然后S 向起点所在的行和列连一条容量无穷大的边,保证不能被割。

汇点T 也是同理。

-1就判一下起点和终点是否在同一行或同一列即可。

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>

#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)

using namespace std;
typedef long long ll;
const ll N=320,M=N<<1;

int n,m,S,T,inf,limit,point;

int lb[M]
,g[M],d[M];
int flow[M][M];
int vh[M],h[M];

inline char readchar()
{
char ch=' ';
for(;ch!='S'&&ch!='T'&&ch!='.'&&ch!='o';ch=getchar());
return ch;
}

inline int min(int a,int b)
{return a<b?a:b;}

int net(int o,int u)
{
if(o==T)return u;
int minh=point+1;
fo(i,1,g[o]<<1){
d[o]=d[o]==g[o]?1:d[o]+1;
int k=lb[o][d[o]];
if(flow[k][o]){
if(h[o]==h[k]+1){
int uu=net(k,min(u,flow[k][o]));
if(uu>0){
flow[k][o]-=uu;
flow[o][k]+=uu;
return uu;
}
if(h[S]>point)return 0;
}
minh=min(minh,h[k]+1);
}
}
--vh[h[o]];
if(vh[h[o]]==0){
h[S]=point+1;
return 0;
}
h[o]=minh;
++vh[h[o]];
return 0;
}
int main()
{
cin>>n>>m;
S=n+m+1,T=S+1,limit=n+m,inf=limit<<1,point=n+m+2;
fo(i,1,n)fo(l,n+1,m+n){
char ch=readchar();
if(ch=='o'){
flow[i][l]=flow[l][i]=1;
lb[i][++g[i]]=l; lb[l][++g[l]]=i;
}
if(ch=='S'){
flow[i][S]=inf; flow[l][S]=inf;
lb[S][++g[S]]=i; lb[S][++g[S]]=l;
}
if(ch=='T'){
flow[T][i]=inf; flow[T][l]=inf;
lb[i][++g[i]]=T; lb[l][++g[l]]=T;
}
}
vh[0]=point; ll ans=0;
while(h[S]<=point)ans+=net(S,inf<<3);
if(ans>limit)puts("-1");else printf("%lld",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: