zoukankan      html  css  js  c++  java
  • [ICPC-Beijing 2006]狼抓兔子

    题面

    很容易看出来是最小割,然后打出模板后发现答案错了(甚至建边都是x->y,我佛了看了半天),一看题解才知道无向图不一样,建图反向边权值也是val,虽然不知道为啥,不过说的是本来就可以增广

    记住就行????

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn=1000005;
    const int maxm=6000005;
    int n,m;
    int s,t;
    int cnt=1,head[maxn];
    struct edge{
        int x,y,val,next;
    }e[maxm];
    
    void add(int x,int y,int val){
        e[++cnt]=(edge){x,y,val,head[x]};
        head[x]=cnt;
    }
    
    void add_edge(int x,int y,int val){
        add(x,y,val);
        add(y,x,val);
    }
    
    int d[maxn];
    bool bfs(){
        queue<int> q;
        memset(d,0,sizeof(d));
        q.push(s);d[s]=1;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            for(int i=head[x];i;i=e[i].next){
                int y=e[i].y;
                if(e[i].val&&!d[y]){
                    d[y]=d[x]+1;
                    q.push(y);
                    if(y==t) return true;
                }
            }
        }
        return false;
    }
    
    int dfs(int x,int flow){
        if(x==t) return flow;
        int rest=flow,k;
        for(int i=head[x];i;i=e[i].next){
            int y=e[i].y;
            if(e[i].val&&d[y]==d[x]+1){
                k=dfs(y,min(rest,e[i].val));
                if(!k) {d[y]=0;continue;}
                e[i].val-=k;
                e[i^1].val+=k;
                rest-=k;
                if(!rest) break;
            }
        }
        return flow-rest;
    }
    
    int dinic(){
        int ret=0;
        while(bfs()) ret+=dfs(s,0x3f3f3f);
        return ret;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        s=1;t=n*m;
        for(int i=1;i<=n;i++)
          for(int j=1;j<m;j++){
               int val;
               scanf("%d",&val);
               add_edge((i-1)*m+j,(i-1)*m+j+1,val);
          }
        for(int i=1;i<n;i++)
          for(int j=1;j<=m;j++){
               int val;
               scanf("%d",&val);
               add_edge((i-1)*m+j,i*m+j,val);
          }
        for(int i=1;i<n;i++)
          for(int j=1;j<m;j++){
              int val;
              scanf("%d",&val);
              add_edge((i-1)*m+j,i*m+j+1,val);
            }
        printf("%d",dinic());
    }
    狼抓兔子
  • 相关阅读:
    【模板】快速幂&取余运算
    【模板】ST表
    LOJ #10070 最小生成树计数
    【模板】KMP字符串匹配
    PL/SQL编程要点和注意点
    数据不同方式的提取和提交的性能测试(转载)
    Oracle分析函数之开窗子句-即WINDOWING子句
    Oracle树反向查询的优化(转载)
    oracle默认的hr用户使用脚本安装
    展开BOM并使用最终用量的算法(转载)
  • 原文地址:https://www.cnblogs.com/sto324/p/11426395.html
Copyright © 2011-2022 走看看