Atcoder KUPC2016 E柵 / Fences 最小割

题意:给你一张图,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

  • 1H100
  • 1W100
  • 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(1jW) character in Si(1iH) 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

Copy
4 5
.....
.....
..X..
.....

Sample Output 1

Copy
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

Copy
2 2
..
.X

Sample Output 2

Copy
-1

In this case, there is no way to keep the goats inside the grid.

Sample Input 3

Copy
6 6
......
......
..X...
.X..X.
..X...
......

Sample Output 3

Copy
10

Fences是一个用于整理和排布电脑桌面图标的软件。首先,你需要下载和安装Fences免费软件,并确保你的系统符合要求(Windows XP/Vista/7)。 一旦安装完成,你可以按照以下步骤使用Fences: 1. 打开Fences软件。在桌面上,你将看到一个默认的"Fence",它是一个用于组织图标的容器。 2. 可以通过拖动桌面上的图标来将其放入Fence中。你可以创建多个Fence来组织不同类别的图标。 3. 如果你想创建一个新的Fence,只需在桌面上点击右键,选择"Fences",然后点击"Create New Fence"。这将在桌面上创建一个新的Fence。 4. 你还可以自定义Fence的属性。右键点击Fence,选择"Configure Fence"。在这里,你可以更改Fence的名称、颜色和透明度等。 5. 如果你不再需要某个Fence,可以将其删除。右键点击Fence,选择"Delete Fence"。这将删除该Fence以及其中的图标。 总的来说,Fences可以帮助你快速整理桌面图标,并将其分组显示,使得你的桌面更加整洁和有序。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【经验分享】F e n c e s 桌面布局软件(Win All)----中文免费版+教程](https://blog.csdn.net/qq_51237779/article/details/127546142)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Fences -让你的桌面图标分组显示,成块状化](https://blog.csdn.net/alex197963/article/details/4806096)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值