• [ZJOI2009]狼和羊的故事


    题目:BZOJ1412、洛谷P2598、Vijos P1555、codevs2351。

    题目大意:有一个nm矩阵,每格里住着狼、羊或其他动物。现在要你建最少的篱笆,使得狼和羊分开。问最少建多长的篱笆。

    解题思路:网络流最小割问题,求最大流即可。

    首先建超级源点S=0,超级汇点T=nm+1。对于每只狼,从S到这只狼连接容量inf的边;对于每只羊,从这只羊到T连接容量inf的边。

    然后,对于每个点,若该点不是羊,则从该点向它四个方向所有不是狼的点连接容量为1的边。

    建完图后就是裸的最大流问题,用Dinic、ISAP等都可,EK应该也可。

    我用的是Dinic。

    C++ Code:

    #include<stdio.h>
    #include<cctype>
    #include<vector>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    #define INF 0x3f3f3f3f
    int n,m,level[30003],iter[30003],a[103][103];
    struct edges{
        int to,cap,rev;
    };
    vector<edges>G[200003];
    queue<int>q;
    inline int readint(){
        int p=0;
        char c=getchar();
        for(;!isdigit(c);c=getchar());
        for(;isdigit(c);c=getchar())p=p*10+c-'0';
        return p;
    }
    inline void addedge(int from,int to,int cap){
        G[from].push_back((edges){to,cap,G[to].size()});
        G[to].push_back((edges){from,0,G[from].size()-1});
    }
    void bfs(int s){
        memset(level,-1,sizeof(level));
        level[s]=0;
        q.push(s);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=0;i<G[u].size();++i){
                edges& e=G[u][i];
                if(level[e.to]<0&&e.cap>0){
                    level[e.to]=level[u]+1;
                    q.push(e.to);
                }
            }
        }
    }
    int dfs(int u,int t,int f){
        if(u==t)return f;
        for(int& i=iter[u];i<G[u].size();++i){
            edges& e=G[u][i];
            if(e.cap>0&&level[e.to]>level[u]){
                int d=dfs(e.to,t,min(f,e.cap));
                if(d){
                    e.cap-=d;
                    G[e.to][e.rev].cap+=d;
                    return d;
                }
            }
        }
        return 0;
    }
    int max_flow(int s,int t){
        int flow=0;
        while(1){
            bfs(s);
            if(level[t]<0)return flow;
            memset(iter,0,sizeof(iter));
            int f;
            while(f=dfs(s,t,INF))flow+=f;
        }
    }
    int main(){
        memset(a,-1,sizeof a);
        n=readint(),m=readint();
        for(int i=1;i<=n;++i)
    	for(int j=1;j<=m;++j)a[i][j]=readint();
        for(int i=1;i<=n;++i)
    	for(int j=1;j<=m;++j){
        	if(a[i][j]==1)addedge(0,(i-1)*m+j,INF);else
        	if(a[i][j]==2)
        	addedge((i-1)*m+j,n*m+1,INF);
        	if(a[i][j]==2)continue;
        	if(a[i+1][j]==2||a[i+1][j]==0)addedge((i-1)*m+j,i*m+j,1);
        	if(a[i-1][j]==2||a[i-1][j]==0)addedge((i-1)*m+j,(i-2)*m+j,1);
        	if(a[i][j+1]==2||a[i][j+1]==0)addedge((i-1)*m+j,(i-1)*m+j+1,1);
        	if(a[i][j-1]==2||a[i][j-1]==0)addedge((i-1)*m+j,(i-1)*m+j-1,1);
        }
        printf("%d
    ",max_flow(0,n*m+1));
        return 0;
    }
    
  • 相关阅读:
    洛谷1098 字符串的展开 解题报告
    洛谷1086 花生采摘 解题报告
    洛谷1125 笨小猴 解题报告
    洛谷1056 排座椅 解题报告
    洛谷1067 多项式输出 解题报告
    洛谷1003 铺地毯 解题报告
    JS在不同js文件中互相调用
    JS鼠标滚轮事件
    JS闭包
    PHP中header('content-type:text/html;charset="utf-8')和error_reporting()的作用
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7612076.html
Copyright © 2020-2023  润新知