• BZOJ1001: [BeiJing2006]狼抓兔子 [最小割 | 对偶图+spfa]


    1001: [BeiJing2006]狼抓兔子

    Time Limit: 15 Sec  Memory Limit: 162 MB
    Submit: 19528  Solved: 4818
    [Submit][Status][Discuss]

    Description

    现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
    而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:

     

    左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 
    1:(x,y)<==>(x+1,y) 
    2:(x,y)<==>(x,y+1) 
    3:(x,y)<==>(x+1,y+1) 
    道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,
    开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击
    这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,
    才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
    狼的数量要最小。因为狼还要去找喜羊羊麻烦.

    Input

    第一行为N,M.表示网格的大小,N,M均小于等于1000.
    接下来分三部分
    第一部分共N行,每行M-1个数,表示横向道路的权值. 
    第二部分共N-1行,每行M个数,表示纵向道路的权值. 
    第三部分共N-1行,每行M-1个数,表示斜向道路的权值. 
    输入文件保证不超过10M

    Output

    输出一个整数,表示参与伏击的狼的最小数量.

    Sample Input

    3 4
    5 6 4
    4 3 1
    7 5 3
    5 6 7 8
    8 7 6 5
    5 5 5
    6 6 6

    Sample Output

    14

    HINT

     2015.4.16新加数据一组,可能会卡掉从前可以过的程序。


    就是用狼把这个图割开
    或者想最多兔子量,然后一个兔子一个狼
     
    法1:dinic
    注意这是无向图
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=1e6+5,INF=1e9;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,m,c,s,t;
    struct edge{
        int v,ne,c,f;
    }e[N*6];
    int cnt,h[N];
    inline void ins(int u,int v,int c){//printf("ins %d %d %d
    ",u,v,c);
        cnt++;
        e[cnt].v=v;e[cnt].c=c;e[cnt].f=0;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].c=c;e[cnt].f=0;e[cnt].ne=h[v];h[v]=cnt;
    }
    inline int id(int i,int j){return (i-1)*m+j;}
    int vis[N],d[N],q[N],head,tail;
    inline void lop(int &x){if(x==N)x=1;}
    bool bfs(){
        memset(vis,0,sizeof(vis));
        memset(d,0,sizeof(d));
        head=tail=1;
        q[tail++]=s;d[s]=0;vis[s]=1;
        while(head!=tail){
            int u=q[head++];lop(head);
            for(int i=h[u];i;i=e[i].ne){
                int v=e[i].v;
                if(!vis[v]&&e[i].c>e[i].f){
                    vis[v]=1;d[v]=d[u]+1;
                    q[tail++]=v;lop(tail);
                    if(v==t) return true;
                }
            }
        }
        return false;
    }
    int cur[N];
    int dfs(int u,int a){
        if(u==t||a==0) return a;
        int flow=0,f;
        for(int &i=cur[u];i;i=e[i].ne){
            int v=e[i].v;
            if(d[v]==d[u]+1&&(f=dfs(v,min(a,e[i].c-e[i].f)))>0){
                flow+=f;
                e[i].f+=f;
                e[((i-1)^1)+1].f-=f;
                a-=f;
                if(a==0) break;
            }
        }
        return flow;
    }
    int dinic(){
        int flow=0;
        while(bfs()){
            for(int i=s;i<=t;i++) cur[i]=h[i];
            flow+=dfs(s,INF);//printf("dinic %d
    ",flow);
        }
        return flow;
    }
    int main(){
        n=read();m=read();s=id(1,1);t=n*m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m-1;j++){c=read();ins(id(i,j),id(i,j+1),c);}
        for(int i=1;i<=n-1;i++)
            for(int j=1;j<=m;j++) {c=read();ins(id(i,j),id(i+1,j),c);}
        for(int i=1;i<=n-1;i++)
            for(int j=1;j<=m-1;j++){c=read();ins(id(i,j),id(i+1,j+1),c);}
        int ans=dinic();
        printf("%d",ans);
    }
    View Code
    法2:对偶图+spfa

    浅析最大最小定理在信息学竞赛中的应用

    对于平面图,对偶图的最短路就是原图的最小割

    直接想也容易理解,最短路就是把一些边割了

    想的时候可以加一条s*到t*的INF的边把s*和t*面割开,但是程序不要加,否则暴增3000ms

    1116ms,dinic用了1684ms

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=2e6+5,INF=1e9;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,m,c,s,t;
    struct edge{
        int v,ne,w;
    }e[N*4];
    int h[N],cnt=0;
    inline void ins(int u,int v,int w){//printf("ins %d %d %d
    ",u,v,w);
        cnt++;
        e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].w=w;e[cnt].ne=h[v];h[v]=cnt;
    }
    inline void lop(int &x){if(x==N) x=1;else if(x==0) x=N-1;}
    int d[N],q[N],head,tail;bool inq[N];
    int spfa(){
        memset(d,127,sizeof(d));
        head=tail=1;
        q[tail++]=s;inq[s]=1;d[s]=0;
        while(head!=tail){
            int u=q[head++];inq[u]=0;lop(head);
            for(int i=h[u];i;i=e[i].ne){
                int v=e[i].v,w=e[i].w;
                if(d[v]>d[u]+w){
                    d[v]=d[u]+w;
                    if(!inq[v]){
                        if(d[v]<d[q[head]]) head--,lop(head),q[head]=v;
                        else q[tail++]=v,lop(tail);
                        inq[v]=1;
                    }
                }
            }
        }
        return d[t];
    }
    int main(){
        n=read();m=read();
        int col=2*(m-1),row=n-1;
        s=0;t=col*row+1;//ins(s,t,INF);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m-1;j++){
                c=read();
                if(i==1) ins(t,(j<<1),c);
                else if(i==n) ins((i-2)*col+(j<<1)-1,s,c);
                else ins((i-2)*col+(j<<1)-1,(i-1)*col+(j<<1),c);
            }
        
        for(int i=1;i<=n-1;i++)
            for(int j=1;j<=m;j++){
                c=read();
                if(j==1) ins(s,(i-1)*col+1,c);
                else if(j==m) ins((i-1)*col+(j<<1)-2,t,c);
                else ins((i-1)*col+(j<<1)-2,(i-1)*col+(j<<1)-1,c);
            }
            
        for(int i=1;i<=n-1;i++)
            for(int j=1;j<=m-1;j++){
                c=read();
                ins((i-1)*col+(j<<1)-1,(i-1)*col+(j<<1),c);
            }
        int ans=spfa();
        printf("%d",ans);
    }
     
     
  • 相关阅读:
    服务的有状态和无状态
    微服务-服务治理
    微服务-服务注册与发现
    微服务-技术的选型
    微服务的数据一致性
    微服务的服务拆分
    初识微服务
    REST API风格
    算法
    JS 判断PC、android、ios、微信浏览器
  • 原文地址:https://www.cnblogs.com/candy99/p/6151526.html
Copyright © 2020-2023  润新知