题意:给你一张图,X是羊,如果羊在图的边界,则羊可以出逃,直接输出-1程序结束.羊只能向上下左右四个方向走,现在你可以在图中的‘.'上安置栅栏,问最少需要多少栅栏才能将其圈住。
这题乍一看是搜索,但是搜索交了两发都wa了,错误在哪知道了但是找不出解决方法,不知道搜索能不能做,后来才发现是个最小割。
思路:我们首先虚拟一个源点和一个汇点,并把图上所有的边界点连接到源点,将所有的羊连接到汇点,这两种边的容量都设为INF,同时,对于羊以外的'.'点(包括边界点),我们把它变成两个点,一个入点,一个出点,并在中间建一条容量为1的边,就相当于把一个点变成了一个边。然后在这个点的出点与其四周点的入点之间建立边,容量为INF。
这样,题目要求我们建栅栏把羊围住,实际上就是将羊到边界的路阻断,易想到最小割,建栅栏实际上是一个删点的操作,我们把一个点变成一条容量为一的边,这样就变成了删边操作,当网络建好以后,模板跑一遍最大流就行了。
学到东西了。
#include<bits/stdc++.h>
#define MEM(a,x) memset(a,x,sizeof(a));
#define MEMINF(a) memset(a,0x3f,sizeof(a));
using namespace std;
typedef long long LL;
const int MAXN=1e5+10;
const int MAXM=2e5+20;
const int INF=0x3f3f3f3f;
const int MOD=1000000007;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
struct MaxFlow{
int head[MAXN];
struct Edge{
int u,v,nex,cap,flow;
}edge[MAXM];
int tot;
int s,t;
int dis[MAXN];
int cur[MAXN];
void Dinic_init(int s,int t){
this->s=s;
this->t=t;
MEM(head,-1);
tot=0;
}
void Addedge(int u,int v,int w) {
edge[tot].v=v,edge[tot].cap=w,edge[tot].flow=0,edge[tot].nex=head[u],head[u]=tot++;
edge[tot].v=u,edge[tot].cap=0,edge[tot].flow=0,edge[tot].nex=head[v],head[v]=tot++;
}
bool bfs() {
MEM(dis,-1);
queue<int>q;
dis[s]=0;
q.push(s);
while (!q.empty()) {
int u=q.front();
q.pop();
for (int i=head[u]; ~i; i=edge[i].nex) {
int v=edge[i].v;
if (edge[i].cap>edge[i].flow&&dis[v]==-1) {
q.push(v);
dis[v]=dis[u]+1;
}
}
}
return dis[t]!=-1;
}
int dfs(int u,int delta) {
if (u==t||delta==0)
return delta;
int ret=0;
int aug;
for(int &i=cur[u]; ~i; i=edge[i].nex) {
int v=edge[i].v;
if (dis[v]==dis[u]+1&&(aug=dfs(v,min(edge[i].cap-edge[i].flow,delta)))>0) {
edge[i].flow+=aug;
edge[i^1].flow-=aug;
delta-=aug;
ret+=aug;
if (delta==0) break;
}
}
//dis[u]=-1;
return ret;
}
void dinic() {
int ret=0;
while(bfs()) {
memcpy(cur,head,sizeof head);
ret+=dfs(s,INF);
}
cout<<ret<<endl;
}
}nima;
int n,m;
int zb(int i,int j) {
return (i*m+j)*2;
}
char mp[110][110];
int main() {
int T,S;
cin>>n>>m;
S=n*m*2+1;
T=S-1;
nima.Dinic_init(T,S);
for (int i=0; i<n; ++i) {
scanf("%s",mp[i]);
}
for (int i=0; i<n; ++i) {
if (mp[i][0]=='X'||mp[i][m-1]=='X') {
puts("-1");
return 0;
}
nima.Addedge(T,zb(i,0),INF);
nima.Addedge(T,zb(i,m-1),INF);
}
for (int i=0; i<m; ++i) {
if (mp[0][i]=='X'||mp[m-1][n]=='X') {
puts("-1");
return 0;
}
nima.Addedge(T,zb(0,i),INF);
nima.Addedge(T,zb(n-1,i),INF);
}
for (int i=0; i<n; ++i)
for (int j=0; j<m; ++j) {
if (mp[i][j]=='X') nima.Addedge(zb(i,j),S,INF);
else {
nima.Addedge(zb(i,j),zb(i,j)+1,1);
}
for (int k=0; k<4; ++k) {
int x=i+dx[k];
int y=j+dy[k];
if (x<0||x>=n||y<0||y>=m)continue;
nima.Addedge(zb(i,j)+1,zb(x,y),INF);
}
}
nima.dinic();
}
Problem Statement
There are some goats on a grid with H rows andW columns. Alice wants to put some fences at some cells where goats do not exist so that no goat can get outside the grid. Goats can move in the four directions, that is, up, down, right and left. Goats can not move onto the cells where fences are placed. If a goat exists at one of the outermost cells in the grid, it can move outside. Goats do not move until all fences are placed. Find the minimum number of fences to be placed.
Constraints
- 1≤H≤100
- 1≤W≤100
- There is at least one goat on the given grid.
Input
The input is given from the Standart Input in the following format:
H W S1 : SH
The j-th(1≤j≤W) character in Si(1≤i≤H) represents whether a goat exists at the cell located at row i and columnj. Character.
represents there is no goat, and X
represents there is one goat at the cell.
Output
Print the minimun number of fences to be placed. If there is no way to keep all the goats inside the grid, print−1.
Sample Input 1
4 5 ..... ..... ..X.. .....
Sample Output 1
4
The optimum answer is to put fences at the cells located at row 3 and column2, row2 and column3, row3 and column4, and row4 and column3.
Sample Input 2
2 2 .. .X
Sample Output 2
-1
In this case, there is no way to keep the goats inside the grid.
Sample Input 3
6 6 ...... ...... ..X... .X..X. ..X... ......
Sample Output 3
10