[BJOI2006][bzoj1001] 狼抓兔子 [最小割]

题面:

传送门

思路:

其实就是一道最小割的题目......

我的写法加了两个优化,常数比较小,所以过掉了

一个是当前弧,一个是若当前点并不能流出去,那么标记dep为-1

听说正解是对偶图最短路?可以找时间学一学......

Code:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define inf 1e9
#define id(i,j) (i-1)*m+j
using namespace std;
inline int read(){
    int re=0,flag=1;char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') flag=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
    return re*flag;
}
int n,m,cnt=-1,ans,first[1000010],dep[1000010],cur[1000010];
int q[1000010],head,tail;
struct edge{
    int to,next,cap;
}a[6000010];
inline void add(int u,int v,int cap){
    a[++cnt]=(edge){v,first[u],cap};first[u]=cnt;
    a[++cnt]=(edge){u,first[v],cap};first[v]=cnt;
}
bool bfs(int s,int t){
    int i,u,v;
    head=0,tail=1;q[0]=s;
    for(i=s;i<=t;i++) dep[i]=-1,cur[i]=first[i];
    dep[s]=1;
    while(head<tail){
        u=q[head++];
        for(i=first[u];~i;i=a[i].next){
            v=a[i].to;
            if(~dep[v]||(!a[i].cap)) continue;
            dep[v]=dep[u]+1;
            q[tail++]=v;
        }
    }
    return ~dep[t];
}
int dfs(int u,int t,int limit){
    if(u==t||!limit) return limit;
    int i,v,f,flow=0;
    for(i=cur[u];~i;i=a[i].next){
        v=a[i].to;cur[u]=i;//优化一
        if(dep[v]==dep[u]+1&&a[i].cap>0){
            f=dfs(v,t,min(limit,a[i].cap));
            if(f){
                flow+=f;limit-=f;
                a[i].cap-=f;a[i^1].cap+=f;
                if(!limit) return flow;
            }
            else{
                dep[v]=-1;continue;//优化二
            }
        }
    }
    return flow;
}
void dinic(int s,int t){
    int tmp;
    while(bfs(s,t)){
        while(tmp=dfs(s,t,inf)) ans+=tmp;
    }
}
int main(){
    memset(first,-1,sizeof(first));
    int i,j,t1;
    n=read();m=read();
    for(i=1;i<=n;i++){
        for(j=1;j<m;j++){
            t1=read();
            add(id(i,j),id(i,j+1),t1);
        }
    }
    for(i=1;i<n;i++){
        for(j=1;j<=m;j++){
            t1=read();
            add(id(i,j),id(i+1,j),t1);
        }
    }
    for(i=1;i<n;i++){
        for(j=1;j<m;j++){
            t1=read();
            add(id(i,j),id(i+1,j+1),t1);
        }
    }
    dinic(1,n*m);
    printf("%d",ans);
}

 

posted @ 2018-02-21 20:51  dedicatus545  阅读(202)  评论(0编辑  收藏  举报