• bzoj1412[ZJOI2009]狼和羊的故事


    bzoj1412[ZJOI2009]狼和羊的故事

    题意:
    n*m网格,每个格子可能为狼、羊或空格。现在要在一些格子边界篱笆使羊狼分开,求最短篱笆。n,m≤100
    题解:

    最小割问题,建一个超级源和超级汇,然后从源点向每只羊之间连边,容量为正无穷;每只狼向汇点连边,容量为正无穷,相邻格子之间连边,容量为1,再跑一次最大流就是结果。因为每一条同时经过羊和狼的路径都需要堵住,但又不能堵连向源点和汇点的边,所以堵住的边必定是将羊和狼分隔开的边。

    dicnic:求解网络流的一种算法:先用bfs构建层次图,然后用dfs沿着层次增广,当dfs无法增广时再重复上述过程,知道源点和汇点不连通。速度比传统的EK法要快得多,但比ISAP慢,因为ISAP无法增广时是直接修改层次,同时还能用gap优化,但dicnic很好写,简洁易懂。CZL大爷说dicnic在计算本来就有一定层次的图(如二分图)时速度快,ISAP在计算一般图速度快,涨姿势了!

    代码:
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <queue>
     5 #define INF 0xfffffff
     6 #define g(b) g[b.x][b.y]
     7 #define h(b) h[b.x][b.y]
     8 #define maxn 110
     9 #define inc(i,j,k) for(int i=j;i<=k;i++)
    10 using namespace std;
    11 
    12 //edge
    13 struct p{int x,y;}; struct e{p t;int c,n;}; e es[200000*2]; int ess,g[maxn][maxn];
    14 void pe(p f,p t,int c){
    15     es[++ess]=(e){t,c,g(f)}; g(f)=ess; 
    16     es[++ess]=(e){f,0,g(t)}; g(t)=ess; 
    17 }
    18 
    19 //maxflow
    20 queue <p> q; int h[maxn][maxn];
    21 bool bfs(p s,p t){//构建层次图 
    22     while(! q.empty())q.pop(); memset(h,-1,sizeof(h)); h(s)=0; q.push(s);
    23     while(! q.empty()){
    24         p now=q.front(); q.pop();
    25         for(int i=g(now);i!=-1;i=es[i].n)if(h(es[i].t)==-1&&es[i].c>0){
    26             h(es[i].t)=h(now)+1; q.push(es[i].t);
    27         }
    28     }
    29     return (h(t)==-1)?0:1;
    30 }
    31 int dfs(p x,p t,int flow){//找增广路并增广 
    32     if(x.x==t.x&&x.y==t.y)return flow;
    33     int used=0;
    34     for(int i=g(x);i!=-1;i=es[i].n)if(es[i].c>0&&h(es[i].t)==h(x)+1){
    35         int w=dfs(es[i].t,t,min(flow,es[i].c));
    36         es[i].c-=w; es[i^1].c+=w; used+=w; flow-=w; if(flow==0)return used;
    37     }
    38     if(! used)h(x)=-1; return used;
    39 }
    40 int dicnic(p s,p t){int flow=0; while(bfs(s,t))flow+=dfs(s,t,INF); return flow;}
    41 
    42 //main
    43 int n,m,graph[maxn][maxn];
    44 int main(){
    45     //freopen("zs.txt","r",stdin);
    46     scanf("%d%d",&n,&m);
    47     inc(i,1,n)inc(j,1,m)scanf("%d",&graph[i][j]);
    48     memset(g,-1,sizeof(g)); ess=-1;
    49     inc(i,1,n)inc(j,1,m){
    50         if(graph[i][j]==2)pe((p){0,0},(p){i,j},INF);
    51         if(graph[i][j]==1)pe((p){i,j},(p){n+1,m+1},INF);
    52         if(i-1>0)pe((p){i,j},(p){i-1,j},1);
    53         if(i+1<=n)pe((p){i,j},(p){i+1,j},1);
    54         if(j-1>0)pe((p){i,j},(p){i,j-1},1);
    55         if(j+1<=m)pe((p){i,j},(p){i,j+1},1);
    56     }
    57     printf("%d",dicnic((p){0,0},(p){n+1,m+1}));    
    58     return 0;
    59 }

    20160102

  • 相关阅读:
    ajax上传文件
    nginx location指令详解
    总结php删除html标签和标签内的内容的方法
    useBuiltIns: 'usage'
    uni-app如何页面传参数的几种方法总结
    基于 schema 的数据校验
    canvas时点击事件和长按冲突
    vue 下载文件流,后台是get方式 ,并且导出出现excel乱码问题
    uni-app canvas 实现文字居中
    git reflog 回退
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5094166.html
Copyright © 2020-2023  润新知