BZOJ1001_狼抓兔子_KEY

题目传送门

由题意得是最小割问题,又由最大流最小割定理可得只需要求无向图的最大流即可。

建双向边,跑Dinic,EK会超时。

注意在DFS时要加"if(!res)dist[now]=0;"这句话,不然会超时。

这句话因为下次DFSnow这个点时得到的最小流量为0,所以就没必要DFS下去,一个剪枝。

code:

/**************************************************************
    Problem: 1001
    User: yekehe
    Language: C++
    Result: Accepted
    Time:1916 ms
    Memory:102480 kb
****************************************************************/
 
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
 
char tc()
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
 
int read()
{
    char c;while(c=tc(),(c<'0'||c>'9')&&c!='-');
    int x=0,y=1;c=='-'?y=-1:x=c-'0';
    while(c=tc(),c>='0'&&c<='9')x=x*10+c-'0';
    return x*y;
}
 
const int MAXN=1000005,MAXM=6000005;
int N,M,ans;
struct edge{
    int to,v;
}L[MAXM];
int head[MAXN],nxt[MAXM],cnt;
int l[MAXM],h,t,S,T,dist[MAXN];
 
void add(int x,int y,int fx,int fy,int c)
{
    int u=(x-1)*M+y,v=(fx-1)*M+fy;
    L[cnt]=(edge){v,c};
    nxt[cnt]=head[u];
    head[u]=cnt;
    cnt++;
}
 
bool BFS()
{
    h=t=0;
    l[++t]=S;
    memset(dist,0,sizeof(dist));
    dist[S]=1;
        while(h<t){
            int front=l[++h];
                for(int i=head[front];i!=-1;i=nxt[i]){
                    int to=L[i].to;
                    if(!dist[to] && L[i].v){
                        dist[to]=dist[front]+1;
                        l[++t]=to;
                    }
                }
        }
    return dist[T];
}
 
int DFS(int now,int x)
{
    if(now==T)return x;
    int res=0;
        for(int i=head[now];i!=-1 && x;i=nxt[i]){
            int to=L[i].to;
            if(dist[to]==dist[now]+1 && L[i].v){
                int fd=DFS(to,min(x,L[i].v));
                x-=fd;L[i].v-=fd;
                res+=fd;L[i^1].v+=fd;
            }
        }
    if(!res)dist[now]=0;
    return res;
}
 
int main()
{
//  freopen("x.txt","r",stdin);
    N=read(),M=read();
    memset(head,-1,sizeof(head));
    register int i,j;
    int c;
        for(i=1;i<=N;i++)for(j=1;j<M;j++)c=read(),add(i,j,i,j+1,c),add(i,j+1,i,j,c);
        for(i=1;i<N;i++)for(j=1;j<=M;j++)c=read(),add(i,j,i+1,j,c),add(i+1,j,i,j,c);
        for(i=1;i<N;i++)for(j=1;j<M;j++)c=read(),add(i,j,i+1,j+1,c),add(i+1,j+1,i,j,c);
    S=1,T=N*M;
        while(BFS()){
            ans+=DFS(S,2e9);
        }
    printf("%d",ans);
    return 0;
}

 

posted @ 2018-01-14 20:21  Cptraser  阅读(155)  评论(0编辑  收藏  举报