网络流sap算法模版

递归版sap:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 310
#define M 50010
#define inf 1<<30
using namespace std;
struct Edge{
    int to,val,next;
}edge[M];
int index[N],d[N],gap[N],e;
void addedge(int from,int to,int val)
{
    edge[e].to=to;
    edge[e].val=val;
    edge[e].next=index[from];
    index[from]=e++;
    edge[e].to=from;
    edge[e].val=0;
    edge[e].next=index[to];
    index[to]=e++;
}
int source,des,n,m;
int dfs(int pos,int flow)
{
    if(pos==des)
        return flow;
    int i,j,v,val,lv,mind,c;
    mind=n-1;//初始最小标号为n-1
    lv=flow;
    for(i=index[pos];i!=-1;i=edge[i].next)
    {
        v=edge[i].to;
        val=edge[i].val;
        if(val)
        {
            if(d[v]+1==d[pos])
            {
                c=min(lv,val);//对于该点的最小可行流
                c=dfs(v,c);
                edge[i].val-=c;//更新剩余图
                edge[i^1].val+=c;
                lv-=c;
                if(d[source]>=n)return flow-lv;
                if(lv==0) break;
            }
            if(d[v]<mind)mind=d[v];//找出与pos相连的点的最小标号
        }
    }
    if(lv==flow)//没有找到增广路劲,进行标号更新
    {
        --gap[d[pos]];
        if(!gap[d[pos]])
            d[source]=n;
        d[pos]=mind+1;
        ++gap[d[pos]];
    }
    return flow-lv;
}
int sap(int st,int de)
{
    source=st;
    des=de;
    memset(d,0,sizeof(d));
    memset(gap,0,sizeof(gap));
    gap[0]=n;//初始标号为0的有n个.
    int ans=0;
    while(d[st]<n)//n是图中点的个数     {
        ans+=dfs(st,inf);
        //cout<<d[st]<<endl;
    }
    return ans;
}
void init()
{
    e=0;
    memset(index,-1,sizeof(index));
}
int main()
{
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        init();
        int i;
        int ll,rr,cap;
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&ll,&rr,&cap);
            addedge(ll,rr,cap);
        }
        printf("%d\n",sap(1,n));     }
    return 0;
}

 非递归版sap:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define Maxn 6010
#define Maxm 200000
#define LL __int64
#define Abs(a) (a)>0?(a):(-a)
using namespace std;
struct Edge{
    int from,to,next;
    LL val;
}edge[Maxm];
int index[Maxn],d[Maxn],gap[Maxn],e,vi[Maxn],n,m;
LL value[Maxn];
LL inf=0;
inline void addedge(int from,int to,LL val)//有向边
{
    edge[e].from=from;
    edge[e].to=to;
    edge[e].val=val;
    edge[e].next=index[from];
    index[from]=e++;
    edge[e].from=to;
    edge[e].to=from;
    edge[e].val=0;
    edge[e].next=index[to];
    index[to]=e++;
}
int prev[Maxn],curr[Maxn];
LL sap(int src,int des,int N)//分别为起点源点和点的数目
{
    bool flag;
    int u=src;
    LL cnt=inf,sum=0;
    memset(d,0,sizeof(d));
    memset(gap,0,sizeof(gap)); gap[0]=N;
    
    while(d[src]!=N)
    {
        flag=false;
        for(int i=index[u];i!=-1;i=edge[i].next)
        {
            if(edge[i].val&&d[edge[i].to]==d[u]-1)
            {
                cnt=min(cnt,edge[i].val);
                prev[edge[i].to]=u;
                curr[edge[i].to]=i;
                u=edge[i].to;
                
                flag=true;
                if(u==des)
                {
                    while(u!=src)
                    {
                        edge[curr[u]].val-=cnt;
                        edge[curr[u]^1].val+=cnt;
                        u=prev[u];
                    }
                    sum+=cnt;
                    cnt=inf;
                }
                else break;
            }
        }
        if(!flag)
        {
            if(!--gap[d[u]]) break;
            else
            {
                d[u]=N;
                for(int i=index[u];i!=-1;i=edge[i].next)
                {
                    if(edge[i].val) d[u]=min(d[u],d[edge[i].to]+1);
                }
                gap[d[u]]++;
                if(u!=src) u=prev[u];
            }
        }
    }
    return sum;
}
void init()
{
    e=0;
    inf=0;
    memset(index,-1,sizeof(index));
    memset(vi,0,sizeof(vi));
}

 

posted @ 2013-06-18 17:02  fangguo  阅读(224)  评论(0编辑  收藏  举报