网络最大流-模板(EK,dinic(+当前弧优化))

1. EK(Edmond—Karp)算法

poj1273

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define max(a,b)   (a>b?a:b)
#define min(a,b)   (a
#define swap(a,b)  (a=a+b,b=a-b,a=a-b)
using namespace std;
typedef long long int LL;
const int MAXL(200);
const int INF(0x3f3f3f3f);
const int MAX(1e6);
const int mod(1e9+7);
int c[MAXL+50][MAXL+50];//残留网络的容量  
int f[MAXL+50];//从源点到当前节点实际还剩多少流量可用 
int pre[MAXL+50];//标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中
int m,n;//n个定点,m条边
int BFS(int sce,int des)
{
    queue<int>q;
    memset(pre,-1,sizeof(pre));//初始化pre数组
    pre[sce]=0;
    f[sce]=INF;
    q.push(sce);
    while(!q.empty())
    {
        int index=q.front();
        q.pop();
        if(index==des)
            break;
        for(int i=1;i<=n;i++)
        {
            if(i!=sce&&c[index][i]>0&&pre[i]==-1)
            {
                pre[i]=index;//记录前驱
                f[i]=min(c[index][i],f[index]);//找增量
                q.push(i);
            }
        }
    }
    return pre[des]==-1? -1:f[des];
}
int MaxFlow(int sce,int des)
{
    int increasement=0;
    int sumflow=0;
    while((increasement=BFS(sce,des))!=-1)
    {
        int k=des;//利用前驱寻找路径
        while(k!=sce)
        {
            int last=pre[k];
            c[last][k]-=increasement;//改变正向边的容量
            c[k][last]+=increasement;//改变反向边的容量
            k=last;
        }
        sumflow+=increasement;
    }
    return sumflow;
}
int main()
{
    ios_base::sync_with_stdio(false);
    while(cin>>m>>n)
    {
        memset(c,0,sizeof(c));
        memset(f,0,sizeof(f));
        for(int i=1;i<=m;i++)
        {
            int st,ed,power;
            cin>>st>>ed>>power;
            c[st][ed]+=power;//输入的时候可能会有相同边不同的流量,所以这里最好用+=
        }
        int ans=MaxFlow(1,n);
        cout<

2.dinic算法

HDU3549

邻接表写法

#include
#include
#include
#include
#include
#include
#include
#define memset(a,v)  memset(a,v,sizeof(a))
#define eps 1.0E-8
using namespace std;
const int MAXL(1000);
const int INF(0x3f3f3f3f);
const int mod(1e9+7);
typedef long long int LL;
struct node
{
    int to,next,cap;
    node() {}
    node(int to,int next,int cap):to(to),next(next),cap(cap) {}
} edge[2*MAXL+50];
int head[MAXL+50];
int level[MAXL+50];
int n,m,cnt;
int BFS(int sc,int st)
{
    queue<int>q;
    memset(level,0);
    level[sc]=1;
    q.push(sc);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(u==st)
            return 1;
        for(int i=head[u]; ~i; i=edge[i].next)
        {
            int v=edge[i].to,c=edge[i].cap;
            if(!level[v] && c)
                level[v]=level[u]+1,q.push(v);
        }
    }
    return 0;
}
int dfs(int sc,int st,int maxFlow)
{
    if(sc==st)
        return maxFlow;
    int flow=0;
    for(int i=head[sc]; ~i; i=edge[i].next)
    {
        int v=edge[i].to,c=edge[i].cap;
        if(level[v]==level[sc]+1 && c>0)
        {
            flow=dfs(v,st,min(maxFlow,c));
            if(flow)
            {
                edge[i].cap-=flow;
                edge[i^1].cap+=flow;
                return flow;
            }
        }
    }
    return 0;

}
int dinic(int sc,int st)
{
    int ans=0;
    while(BFS(sc,st))
        ans+=dfs(sc,st,INF);
    return ans;
}
void add_edge(int u,int v,int w)
{
    edge[cnt]=node(v,head[u],w);
    head[u]=cnt++;
}
void init()
{
    cnt=0;
    memset(head,-1);
}
int main()
{
    int T;
    scanf("%d",&T);
    int CASE=1;
    while(T--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=1; i<=m; i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add_edge(x,y,z);
            add_edge(y,x,0);
        }
        int ans=dinic(1,n);
        cout<<"Case "<": ";
        cout<

当前弧优化版本

#include
#include
#include
#include
#include
#include
#include
#define memset(a,v)  memset(a,v,sizeof(a))
#define eps 1.0E-8
using namespace std;
const int MAXL(1000);
const int INF(0x3f3f3f3f);
const int mod(1e9+7);
typedef long long int LL;
struct node
{
    int to,next,cap;
    node() {}
    node(int to,int next,int cap):to(to),next(next),cap(cap) {}
} edge[2*MAXL+50];
int head[MAXL+50];
int level[MAXL+50];
int current[MAXL+50];
int n,m,cnt;
int BFS(int sc,int st)
{
    queue<int>q;
    memset(level,0);
    for(int i=0;i<=n;i++) current[i]=head[i];//初始化current数组
    level[sc]=1;
    q.push(sc);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(u==st)
            return 1;
        for(int i=head[u]; ~i; i=edge[i].next)
        {
            int v=edge[i].to,c=edge[i].cap;
            if(!level[v] && c)
                level[v]=level[u]+1,q.push(v);
        }
    }
    return 0;
}
int dfs(int sc,int st,int maxFlow)
{
    if(sc==st)
        return maxFlow;
    int flow=0;
    for(int i=current[sc]; ~i; i=edge[i].next)//当前弧优化
    {
        current[sc]=i;
        int v=edge[i].to,c=edge[i].cap;
        if(level[v]==level[sc]+1 && c>0)
        {
            flow=dfs(v,st,min(maxFlow,c));
            if(flow)
            {
                edge[i].cap-=flow;
                edge[i^1].cap+=flow;
                return flow;
            }
        }
    }
    return 0;

}
int dinic(int sc,int st)
{
    int ans=0;
    while(BFS(sc,st))
        ans+=dfs(sc,st,INF);
    return ans;
}
void add_edge(int u,int v,int w)
{
    edge[cnt]=node(v,head[u],w);
    head[u]=cnt++;
}
void init()
{
    cnt=0;
    memset(head,-1);
}
int main()
{
    int T;
    scanf("%d",&T);
    int CASE=1;
    while(T--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=1; i<=m; i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add_edge(x,y,z);
            add_edge(y,x,0);
        }
        int ans=dinic(1,n);
        cout<<"Case "<": ";
        cout<

这几天做了一道HDU 3416 上面的代码卡时间了。
一直没找出原因,后来不停的debug之后发现是上面的dfs写的其实不好,递归次数可能不是最优的。

那么换一个:


int dfs(int u,int des,int increaseRoad)
{
    if(u==des)
        return increaseRoad;
    int ret=0;
    for(int k=head[u]; k!=-1; k=edge[k].next)
    {
        int v = edge[k].to,w=edge[k].cap;
        if(level[v]==level[u]+1&&w!=0)
        {
            int MIN = min(increaseRoad-ret,w);
            w = dfs(v,des,MIN);
            if(w > 0)
            {
                edge[k].cap-=w;
                edge[k^1].cap+=w;
                ret+=w;
                if(ret==increaseRoad)
                    return ret;
            }
        }
    }
    return ret;
}

你可能感兴趣的:(一些算法模板,图论)