[BeiJing2006 狼抓兔子] 最大流

From: http://www.lydsy.com/JudgeOnline/problem.php?id=1001

Solution:

这题用sap水过了, 更快的做法是转化成平面图来搞?

/**************************************************************
    Problem: 1001
    User: leezy
    Language: C++
    Result: Accepted
    Time:1292 ms
    Memory:141744 kb
****************************************************************/
 
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <queue>
#include <stack>
#include <functional>
using namespace std;
const double dnf=10000000000.f;
const int inf=0x7fffffff;
const int maxn=1001*1001;
struct edge{
    int lnk,to;
    int c;
}e[maxn*10];
int  adj[maxn],now;
int  d[maxn],g[maxn],p[maxn],v[maxn],r[maxn];
queue<int>  Q;
void  init(int n)
{//初始化顶点集
    for(int i=0;i<=n;++i)adj[i]=-1;
    now=0;
}
void  ins(int a,int b,int c=0)
{//添加有向边.back为反向边的边号
    e[now].lnk=adj[a],e[now].to=b,e[now].c=c;
    adj[a]=now++;
}
void  add(int a,int b,int c=0)
{
    ins(a,b,c);
    ins(b,a);
}
void  bfs(int t)
{
    Q.push(t);d[t]=0;
    while(!Q.empty()){//计算广搜树
        int u(Q.front());Q.pop();
        ++g[d[u]];
        for(int i=adj[u];i!=(-1);i=e[i].lnk){
            if(e[i^1].c>0&&d[e[i].to]==inf){
               d[e[i].to]=d[u]+1;Q.push(e[i].to);
            }
        }
    }
}
void  relabel(int u,int m)
{
    int dm=m;//初始化为顶点数
    for(int i=adj[u];i!=(-1);i=e[i].lnk)
    dm=(e[i].c>0&&d[e[i].to]<dm)?(d[e[i].to]):(dm);
    d[u]=dm+1;
}
int  sap(int s,int t,int m)
{
    int ans=0,cf0=inf;
    for(int i=0;i<=m;++i) //初始化sap参数
    d[i]=inf,g[i]=0,v[i]=adj[i],
    p[i]=-1,r[i]=0;
    bfs(t);//从汇点bfs
    for(int u(s);d[s]<m;){//从源点开始
        if(u==t){
            ans+=cf0;
            for(int i=t;p[i]!=(-1);i=p[i])
            e[r[i]].c-=cf0,e[r[i]^1].c+=cf0;
            u=s,cf0=dnf;
        }
        int  old(u);
        for(int i=v[u];i!=(-1);i=e[i].lnk){
            if(d[e[i].to]+1!=d[u]) continue;
            if(e[i].c==0) continue;
            if(cf0>e[i].c)cf0=e[i].c;
            r[e[i].to]=i;p[e[i].to]=u;v[u]=i;u=e[i].to;break;
        }
        if(old==u){
            if(0==(--g[d[u]])) break;
            v[u]=adj[u];r[u]=0;
            relabel(u,m);++g[d[u]];
            if(u!=s){//交换p[u],u 重置p[u]
                int pu=p[u];  p[u]=-1;u=pu;
            }
        }
    }
    return ans;
}
int main()
{
    //const char path[] = "D:\\Project\\AlgorithmExam\\test.txt";
    //freopen(path, "r+", stdin);
 
    int n,m;
    while( scanf("%d%d", &n, &m) != EOF ){
        init(n*m);
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < m-1; ++j){
            int I = i*m + j, J = I + 1, x;
            scanf("%d", &x);
            add( I, J, x ); add( J, I, x );
        }
        for (int i = 0; i < n-1; ++i)
            for (int j = 0; j < m; ++j){
            int I = i*m + j, J = (i+1)*m + j, x;
            scanf("%d", &x);
            add( I, J, x ); add( J, I, x );
        }
        for (int i = 0; i < n-1; ++i)
            for (int j = 0; j < m-1; ++j){
            int I = i*m + j, J = (i+1)*m + j + 1, x;
            scanf("%d", &x);
            add( I, J, x );
        }
        printf("%d\n", sap(0, n*m-1, n*m));
    }
    return 0;
}
View Code

 

posted on 2013-12-07 21:25  leezyli  阅读(169)  评论(0编辑  收藏  举报

导航