最大流的Dinic算法

具体Dinic的思路我不再赘述,主要说一下里面比较神奇的优化。

题目:方格取数2

主要的优化在于(我的初步理解,可能不正确,求指正):当我从某一个点出发没有取得任何流量的时候,这个点可以标记为不可用,用来提高效率。

没加优化之前HDU上的裸最大流都是可以A的,但是方格取数2就T掉(5000ms),加了优化31msA掉。

代码:

#include<iostream>
#include<cstring>
#include<queue>
#include<climits>
#include<limits.h>
#include<cstdio>

using namespace std;

const long long INF=0x3f3f3f3f;

struct no{
    long long next,tar,flow;
}edge[1000020];

long long head[10000],k,deep[10000],S,T;

void init()
{
    k=0;
    memset(head,-1,sizeof(head));
}

void addEdge(long long s,long long t,long long f)
{
    edge[k].tar=t;
    edge[k].flow=f;
    edge[k].next=head[s];
    head[s]=k++;
}

bool buildLevelGraph()
{
    memset(deep,-1,sizeof(deep));
    queue<long long> q;
    q.push(S);
    deep[S]=0;
    while(!q.empty())
    {
        long long x;
        x=q.front();
        q.pop();
        if(x==T)return true;
        for(long long i=head[x];i!=-1;i=edge[i].next)
        {
            if(deep[edge[i].tar]==-1 && edge[i].flow>0)
            {
                deep[edge[i].tar]=deep[x]+1;
                q.push(edge[i].tar);
            }
        }
    }
    return false;
}

long long extend(long long p,long long maxn)
{
    if(p==T)return maxn;
    long long tflow,pf=0;
    for(long long i=head[p];i!=-1;i=edge[i].next)
    {
        if(edge[i].flow>0 && deep[edge[i].tar]==deep[p]+1)
        {
            tflow=extend(edge[i].tar,min(maxn-pf,edge[i].flow));
            pf+=tflow;
            edge[i].flow-=tflow;
            edge[i^1].flow+=tflow;
            //if(pf==maxn)return pf;
        }
    }
    if(!pf)
    {
        deep[p]=-2;//就是这里,标记点不可用
    }
    return pf;
}

long long Dinic(long long s,long long t)
{
    long long res=0,fl=0;
    while(buildLevelGraph())
    {
       res+=extend(s,INF);
    }
    return res;
}
long long m,n,sum;
bool legal(int tx,int ty)
{
    if(tx>=1&&tx<=m&&ty>=1&&ty<=n)return true;
    return false;
}

int walk[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

int main()
{
    while(~scanf("%d%d",&m,&n))
    {
        init();
        T=m*n+1;
        sum=0;
        S=0;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                int t;
                cin>>t;
                sum+=t;
                if((i+j)%2==0)
                {
                    addEdge(S,(i-1)*n+j,t);
                    addEdge((i-1)*n+j,S,0);
                    for(int z=0;z<4;z++)
                    {
                        int x,y;
                        x=i+walk[z][0];
                        y=j+walk[z][1];
                        if(legal(x,y))
                        {
                            addEdge((i-1)*n+j,(x-1)*n+y,INF);
                            addEdge((x-1)*n+y,(i-1)*n+j,0);
                        }
                    }
                }
                else
                {
                    addEdge((i-1)*n+j,T,t);
                    addEdge(T,(i-1)*n+j,0);
                    for(int z=0;z<4;z++)
                    {
                        int x,y;
                        x=i+walk[z][0];
                        y=j+walk[z][1];
                        if(legal(x,y))
                        {
                            addEdge((x-1)*n+y,(i-1)*n+j,INF);
                            addEdge((i-1)*n+j,(x-1)*n+y,0);
                        }
                    }
                }
            }
        }

        int maxflow=Dinic(S,T);
        printf("%d\n",sum-maxflow);
    }
}

你可能感兴趣的:(最大流的Dinic算法)