Pleasant sheep and big big wolf (hdu 3046 最小割)

Pleasant sheep and big big wolf

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2371    Accepted Submission(s): 988

Problem Description

In ZJNU, there is a well-known prairie. And it attracts pleasant sheep and his companions to have a holiday. Big big wolf and his families know about this, and quietly hid in the big lawn. As ZJNU ACM/ICPC team, we have an obligation
to protect pleasant sheep and his companions to free from being disturbed by big big wolf. We decided to build a number of unit fence whose length is 1. Any wolf and sheep can not cross the fence. Of course, one grid can only contain an animal.

Now, we ask to place the minimum fences to let pleasant sheep and his Companions to free from being disturbed by big big wolf and his companions.

Input

There are many cases.

For every case:

N and M(N,M<=200)

then N*M matrix:

0 is empty, and 1 is pleasant sheep and his companions, 2 is big big wolf and his companions.

Output

For every case:

First line output “Case p:”, p is the p-th case;

The second line is the answer.

Sample Input

4 6
1 0 0 1 0 0
0 1 1 0 0 0
2 0 0 0 0 0
0 2 0 1 1 0

Sample Output

Case 1:
4

Source

2009 Multi-University Training Contest 14 - Host by ZJNU

Recommend

gaojie   |   We have carefully selected several similar problems for you:  1569 1565 3049 3045 1733

题意:一个矩阵,1表示羊,2表示狼,然后让把羊和狼隔开,问需要最小的栅栏数。

思路:要把羊和狼隔开,就是去最小割把他们分开,每个格子和周围四个格子建流量为1的边,s向狼建INF的边,羊向t建INF的边。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

const int MAXM = 200010;
const int MAXN = 43000;

int n,m,N;
int mp[205][205];

struct Edge
{
    int to,next,cap,flow;
}edge[MAXM];

int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];

void init(int n)
{
    tol=0;N=n;
    memset(head,-1,sizeof(head));
}

//加边,单向图三个参数,双向图四个参数
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u];
    edge[tol].flow=0; head[u]=tol++;
    edge[tol].to=u; edge[tol].cap=rw; edge[tol].next=head[v];
    edge[tol].flow=0; head[v]=tol++;
}

//输入参数:起点,终点,点的总数
//点的编号没有影响,只要输入点的总数
int sap(int start,int end,int N)
{
    memset(gap,0,sizeof(gap));
    memset(dep,0,sizeof(dep));
    memcpy(cur,head,sizeof(head));
    int u=start;
    pre[u]=-1;
    gap[0]=N;
    int ans=0;
    while (dep[start]<N)
    {
        if (u==end)
        {
            int Min=INF;
            for (int i=pre[u];i!=-1;i=pre[edge[i^1].to])
                if (Min>edge[i].cap-edge[i].flow)
                    Min=edge[i].cap-edge[i].flow;
            for (int i=pre[u];i!=-1;i=pre[edge[i^1].to])
            {
                edge[i].flow+=Min;
                edge[i^1].flow-=Min;
            }
            u=start;
            ans+=Min;
            continue;
        }
        bool flag=false;
        int v;
        for (int i=cur[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].to;
            if (edge[i].cap-edge[i].flow && dep[v]+1==dep[u])
            {
                flag=true;
                cur[u]=pre[v]=i;
                break;
            }
        }
        if (flag)
        {
            u=v;
            continue;
        }
        int Min=N;
        for (int i=head[u];i!=-1;i=edge[i].next)
            if (edge[i].cap-edge[i].flow && dep[edge[i].to]<Min)
            {
                Min=dep[edge[i].to];
                cur[u]=i;
            }
        gap[dep[u]]--;
        if (!gap[dep[u]]) return ans;
        dep[u]=Min+1;
        gap[dep[u]]++;
        if (u!=start) u=edge[pre[u]^1].to;
    }
    return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("C:/Users/asus1/Desktop/IN.txt","r",stdin);
#endif
    int i,j,cas=0;
    while (~sff(n,m))
    {
        for (i=0;i<n;i++)
            for (j=0;j<m;j++)
                sf(mp[i][j]);
        init(n*m+2);
        int s=n*m,t=s+1;
        for (i=0;i<n;i++)
        {
            for (j=0;j<m;j++)
            {
                if (i>0)
                    addedge(i*m+j,(i-1)*m+j,1);
                if (j>0)
                    addedge(i*m+j,i*m+j-1,1);
                if (i<(n-1))
                    addedge(i*m+j,(i+1)*m+j,1);
                if (j<(m-1))
                    addedge(i*m+j,i*m+j+1,1);
                if (mp[i][j]==1)
                    addedge(i*m+j,t,INF);
                if (mp[i][j]==2)
                    addedge(s,i*m+j,INF);
            }
        }
        pf("Case %d:\n",++cas);
        pf("%d\n",sap(s,t,N));
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 22:36:05

Pleasant sheep and big big wolf (hdu 3046 最小割)的相关文章

HDU 3046-Pleasant sheep and big big wolf(网络流_最小割)

Pleasant sheep and big big wolf Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2254    Accepted Submission(s): 946 Problem Description In ZJNU, there is a well-known prairie. And it attracts p

hdu 3046 最小割

每个栅栏其实就是一条边,修一些栅栏,使得狼不能抓到羊,其实就是求一个割,使得羊全在S中,狼全在T中. 1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <queue> 5 #define maxn 40010 6 #define oo 0x3f3f3f3f 7 #define clr(arr,n) memset(&arr,0,sizeof(arr[0])*(

HDU 3046Pleasant sheep and big big wolf(切最小网络流)

职务地址:HDU 3046 最小割第一发!事实上也没什么发不发的. ..最小割==最大流.. 入门题,可是第一次入手最小割连入门题都全然没思路... sad..对最小割的本质还是了解的不太清楚.. 这题就是对每两个相邻的格子的边界都要进行加边,然后求最大流就OK了. RE了好长时间,注意遍历加边的时候要从1開始,而不是0開始,由于0是源点的.. .(或许仅仅有我才犯这样的错误吧. . .)建图不多说了..仅仅要了解了最小割,建图还是非常easy想的. 代码例如以下: #include <iost

HDU 3046 Pleasant sheep and big big wolf

Pleasant sheep and big big wolf Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 304664-bit integer IO format: %I64d      Java class name: Main In ZJNU, there is a well-known prairie. And it attracts pleasant

HDU 3046 Pleasant sheep and big big wolf(最小割)

HDU 3046 Pleasant sheep and big big wolf 题目链接 题意:一个n * m平面上,1是羊,2是狼,问最少要多少围墙才能把狼全部围住,每有到达羊的路径 思路:有羊和狼,要分成两个集合互不可达,显然的最小割,建图源点连狼,容量无穷,羊连汇点,容量无穷,然后相邻格子连边,容量为1 代码: #include <cstdio> #include <cstring> #include <queue> #include <algorithm

hdoj 3046 Pleasant sheep and big big wolf 【最小割】

Pleasant sheep and big big wolf Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2570    Accepted Submission(s): 1056 Problem Description In ZJNU, there is a well-known prairie. And it attracts

Pleasant sheep and big big wolf

点击打开链接 题目:在一个N * M 的矩阵草原上,分布着羊和狼,每个格子只能存在0或1只动物.现在要用栅栏将所有的狼和羊分开,问怎么放,栅栏数放的最少,求出个数? 解析:将狼群看作一个集合,羊群看作一个集合.然后设置源点和汇点,将两点至存在动物的点的距离赋值为1,构图,由于求得是栅栏数,从存在动物的位置向四周发散点赋值为1,即该方向放置一个栅栏.然后可以发现变成了求最小割,即求出最大流.需要注意的是,由于数据比较大,200 * 200.如果设置源点和汇点相差较大(即s = 0,e = n *

hdu 3657 最小割的活用 / 奇偶方格取数类经典题 /最小割

题意:方格取数,如果取了相邻的数,那么要付出一定代价.(代价为2*(X&Y))(开始用费用流,敲升级版3820,跪...) 建图:  对于相邻问题,经典方法:奇偶建立二分图.对于相邻两点连边2*(X&Y),源->X连边,Y->汇连边,权值w为点权. ans=总点权-最小割:如果割边是源->X,表示x不要选(是割边,必然价值在路径上最小),若割边是Y-汇点,同理:若割边是X->Y,则表示选Y点且选X点, 割为w( 2*(X&Y) ). 自己的确还没有理解其本质

hdu 3046 Pleasant sheep and big big wolf 最小割

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3046 In ZJNU, there is a well-known prairie. And it attracts pleasant sheep and his companions to have a holiday. Big big wolf and his families know about this, and quietly hid in the big lawn. As ZJNU A