zoukankan      html  css  js  c++  java
  • 洛谷P2598 [ZJOI2009]狼和羊的故事

    题目描述

    “狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。 Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。

    输入输出格式

    输入格式:

    文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。

    输出格式:

    文件中仅包含一个整数ans,代表篱笆的最短长度。

    输入输出样例

    输入样例#1: 复制
    2 2
    2 2 
    1 1 
    输出样例#1: 复制
    2
    

    说明

    数据范围

    10%的数据 n,m≤3

    30%的数据 n,m≤20

    100%的数据 n,m≤100

    最小割的模型

    一开始傻逼了。。上来就把正解否定了。。

    源点向狼连边

    狼向羊连边(狼吃羊hhh)

    羊向汇点连边

    空地之间互相连边

    狼向空地连边

    空地向羊连边

    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int MAXN=200001,INF=2*1e9+10;
    inline char nc()
    {
        static char buf[MAXN],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        char c=nc();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();}
        return x*f;
    }
    int S=0,T=301;
    struct node
    {
        int u,v,flow,nxt;
    }edge[MAXN*20];
    int head[MAXN],cur[MAXN],num=0;
    inline void add_edge(int x,int y,int z)
    {
        edge[num].u=x;
        edge[num].v=y;
        edge[num].flow=z;
        edge[num].nxt=head[x];
        head[x]=num++;
    }
    inline void AddEdge(int x,int y,int z) 
    {
        add_edge(x,y,z);
        add_edge(y,x,0);
    }int deep[MAXN];
    inline bool BFS()
    {
        memset(deep,0,sizeof(deep));
        deep[S]=1;
        queue<int>q;
        q.push(S);
        while(q.size()!=0)
        {
            int p=q.front();
            q.pop();
            for(int i=head[p];i!=-1;i=edge[i].nxt)
                if(!deep[edge[i].v]&&edge[i].flow)
                {
                    deep[edge[i].v]=deep[p]+1;q.push(edge[i].v);
                    if(edge[i].v==T) return 1;
                }
        }
        return deep[T];
    }
    int DFS(int now,int nowflow)
    {
        if(now==T||nowflow<=0)    return nowflow;
        int totflow=0;
        for(int &i=cur[now];i!=-1;i=edge[i].nxt) 
        {
            if(deep[edge[i].v]==deep[now]+1&&edge[i].flow)
            {
                int canflow=DFS(edge[i].v,min(nowflow,edge[i].flow));
                edge[i].flow-=canflow;edge[i^1].flow+=canflow;
                totflow+=canflow;
                nowflow-=canflow;
                if(nowflow<=0) break;
            }
        }
        return totflow;
    }
    int Dinic()
    {
        int ans=0;
        while(BFS())
        {
            memcpy(cur,head,sizeof(head)); 
            ans+=DFS(S,INF);
        }
        return ans;
    }
    int xx[6]={0,-1,+1,0,0},yy[6]={0,0,0,-1,+1};
    int a[1001][1001],belong[1001][1001];
    int N,M;
    int main()
    {
        #ifdef WIN32
        freopen("a.in","r",stdin);
        #else
        #endif
        memset(head,-1,sizeof(head));
        N=read();M=read();T=N*M+2;
           for(int i=1;i<=N;i++)
            for(int j=1;j<=M;j++)
                a[i][j]=read(),belong[i][j]=(i-1)*M + j;
        for(int i=1;i<=N;i++)
            for(int j=1;j<=M;j++)
            {
                if(a[i][j]==1) 
                {
                    AddEdge(S,belong[i][j],INF);
                    for(int k=1;k<=4;k++)
                        if( i+xx[k] >= 1 && i+xx[k] <= N && j+yy[k] >= 1 && j+yy[k]<=M && a[i][j] != a[i+xx[k]][j+yy[k]])
                            AddEdge(belong[i][j],belong[i+xx[k]][j+yy[k]],1);
                }
                else if(a[i][j]==2) 
                {
                    AddEdge(belong[i][j],T,INF);
                    for(int k=1;k<=4;k++)
                        if( i+xx[k] >= 1 && i+xx[k] <= N && j+yy[k] >= 1 && j+yy[k]<=M && a[i+xx[k]][j+yy[k]] == 0 )
                            AddEdge(belong[i+xx[k]][j+yy[k]],belong[i][j],1);
                }
                else
                {
                    for(int k=1;k<=4;k++)
                        if( i+xx[k] >= 1 && i+xx[k] <= N && j+yy[k] >= 1 && j+yy[k]<=M && a[i+xx[k]][j+yy[k]] == 0)
                            AddEdge(belong[i][j],belong[i+xx[k]][j+yy[k]],1);
                }
            }
        printf("%d",Dinic());
        return  0;
    }
  • 相关阅读:
    ubuntu
    什么是守护进程?
    Redis 简介
    什么是原子性,什么是原子性操作?
    什么是BSD协议?
    查看内存
    数据库备份与还原
    PostgreSQL 判断字符串包含的几种方法
    SQL 基础
    手风琴-过渡效果,显示隐藏列表案例
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/8410053.html
Copyright © 2011-2022 走看看