网络流dinic最大流板子 bzoj[1001]

传送门

bzoj【1001】最小割最大流

据说此题是对偶图最短路~~~

最大流过了,就当是练网络流了吧

代码如下

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int n,m;
int fst[1000005];
int nxt[6000005];
int v[6000005];
int k[6000005];
int d[1000005];
int edge=1;
int S,T;
const int inf=1000000000;
void add(int x,int y,int val)
{
    edge++;
    nxt[edge]=fst[x];
    fst[x]=edge;
    v[edge]=y;
    k[edge]=val;
}
queue <int> q;
bool bfs()
{
    while(!q.empty())q.pop();
    memset(d,-1,sizeof(d));
    d[S]=1;q.push(S);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=fst[x];i;i=nxt[i])
        {
        if(k[i]&&d[v[i]]==-1)   
        {
        d[v[i]]=d[x]+1; 
        q.push(v[i]);
        }   
        }
    }
    return ~d[T];
}
int dfs(int x,int val)
{
    if(x==T||!val)return val;
    int tmp=0;
    for(int i=fst[x];i;i=nxt[i])
    {
        if(k[i]&&d[v[i]]==d[x]+1)
        {
            int flow=dfs(v[i],min(val,k[i]));
            val-=flow;k[i^1]+=flow;k[i]-=flow,tmp+=flow;
            if(!v)break;
        }
    }
    if(!tmp)d[x]=-1;
    return tmp;
}
int dinic()
{
    int tmp=0;
    while(bfs())tmp+=dfs(S,inf);
    return tmp;
}
int main()
{
    scanf("%d%d",&n,&m);
    int x;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m-1;j++)
    {
    scanf("%d",&x);
    int y=(i-1)*m+j;
    add(y,y+1,x);
    add(y+1,y,x);   
    }
    for(int i=1;i<=n-1;i++)
    for(int j=1;j<=m;j++)
    {
    scanf("%d",&x); 
    int y=(i-1)*m+j;
    add(y,y+m,x);
    add(y+m,y,x);   
    }
    for(int i=1;i<n;i++)
    for(int j=1;j<m;j++)
    {
    scanf("%d",&x); 
    int y=(i-1)*m+j;
    add(y,y+m+1,x); 
    add(y+m+1,y,x);     
    }
    S=1;
    T=n*m;
    printf("%d",dinic());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/richard__luan/article/details/81009702