题意
你的敌对势力计划在一个网格状的迷宫里进行交易。迷宫共有n 行m 列,
其中一些房间有障碍物无法通行。敌对势力需要从房间S 走到房间T (房间S
和房间T 都没有障碍物)。他们拥有蓝月套装,因此每次可以从一个房间移动
到一个位于同一行或者同一列且没有障碍物的房间。为了阻止敌对势力的交易,
你需要在房间S 和房间T 以外的一些可通行房间内放入障碍,使得他们无法从
房间S 走到房间T。请计算出最少要在多少个房间放障碍。
2<=n,m<=100
分析
很快可以想到,把点拆开,然后中间流一条1的边,割掉花费1,然后一个变成进入的点,一个变成出去的点
这样如果直接每行每列连边的话,是N^2级别的,我们考虑对于一个每行和每列都建一个辅助点,然后就可以变成N+M的级别了
代码
#include <bits/stdc++.h>
#define num(i,j,k) ((((i)-1)*m+(j))*2+k)
using namespace std;
const int N = 1000010;
const int inf = 1e9;
inline int read()
{
int p=0; int f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
struct node
{
int x,y,c,next;
}edge[N]; int len,first[N];
void ins(int x,int y,int c)
{
len++; edge[len].x=x; edge[len].y=y; edge[len].c=c; edge[len].next=first[x]; first[x]=len;
len++; edge[len].x=y; edge[len].y=x; edge[len].c=0; edge[len].next=first[y]; first[y]=len;
}
int n,m; char str[310][310]; int s,d; int tot;
queue<int>q; int dep[N];
bool bfs()
{
while(!q.empty()) q.pop(); q.push(s);
for(int i=1;i<=tot+n+m;i++) dep[i] = 0; dep[s] = 1;
while(!q.empty())
{
int x = q.front();
for(int k=first[x];k!=-1;k=edge[k].next)
{
int y = edge[k].y;
if(dep[y] == 0 && edge[k].c)
{
dep[y] = dep[x] + 1;
q.push(y);
}
}
q.pop();
}
return dep[d] > 0;
}
int dfs(int x,int flow)
{
if(x==d || flow == 0) return flow;
int delta=0;
for(int k=first[x];k!=-1;k=edge[k].next)
{
int y = edge[k].y;
if(dep[y] == dep[x] + 1 && edge[k].c && flow > delta)
{
int minf = dfs(y,min(flow - delta , edge[k].c));
edge[k].c-=minf; edge[k^1].c+=minf;
delta+=minf;
}
}
if(delta==0) dep[x] = 0;
return delta;
}
int main()
{
len = 1; memset(first,-1,sizeof(first));
n = read(); m = read();
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
{
scanf("\n%c",&str[i][j]);
if(str[i][j] == 'S') s = num(i,j,0);
else if(str[i][j] == 'T') d = num(i,j,1);
}
tot = num(n,m,1);
for(int i=1;i<=n;i++) // tot + i
{
for(int j=1;j<=m;j++) // tot + n + j
{
if(str[i][j] == '.') continue;
if(str[i][j] == 'o') ins(num(i,j,0) , num(i,j,1) , 1);
else ins(num(i,j,0) , num(i,j,1) , inf);
ins(num(i,j,1) , tot+i , inf);
ins(num(i,j,1) , tot+n+j , inf);
ins(tot+i , num(i,j,0) , inf);
ins(tot+n+j , num(i,j,0) , inf);
// printf("(%d,%d) , %d %d\n",i,j,i,j);
}
}
int ans = 0;
while(bfs())
ans+=dfs(s,inf);
return printf("%d\n",(ans >= inf) ? -1 : ans),0;
}