网络流

EK求最大流。复杂度O(n*m*m)。

EK求最大流。复杂度O(n*m*m)。
#include <queue>
#include <stdio.h>
#include <string.h>

using namespace std;

#define N 205
#define M 405
#define INF 0x7fffffff

#define min(a,b) a < b ?  a : b
#define CLR(a,v) memset(a,v,sizeof(a))

struct Vertex
{
    int head;
}V[N];

struct Edge
{
    Edge(){}
    Edge(int v,int c,int f,int ne):v(v),c(c),f(f),next(ne){}
}E[M];

int pre[N],flow[N];

int top,s,t;

void Init()
{
    top = 0;
    CLR(V,-1);
}

void Add_edge(int u,int v,int c)
{
    E[top] = Edge(v,c,0,V[u].head);
    V[u].head = top++;
    E[top] = Edge(u,0,0,V[v].head);
    V[v].head = top++;
}

bool Ed_Karp()
{
    CLR(flow,0);
    queue<int> Q;
    Q.push(s);
    flow[s] = INF;
    while(!Q.empty())
    {
        int u = Q.front();
        for(int i=V[u].head;i!=-1;i=E[i].next)
        {
            int v = E[i].v;
            if(!flow[v] && E[i].c > E[i].f)
            {
                pre[v] = i;
                flow[v] = min(flow[u],E[i].c-E[i].f);		//flow[v] represents the min flow in the way from "s" to "v".
                if(v == t)
                    return true;
                Q.push(v);
            }
        }
        Q.pop();
    }
    return false;
}

int Ford_Fulkerson()
{
    int i,MaxFlow = 0;
    while(Ed_Karp())
    {
        for(int v=t;v!=s;v=E[i^1].v)
        {
            i = pre[v];
            E[i].f   += flow[t];
            E[i^1].f -= flow[t];        //cool
        }
        MaxFlow += flow[t];
    }
    return MaxFlow;
}


SAP求最大流。复杂度O(n*n*m)。
#include <queue>
#include <stdio.h>
#include <string.h>

using namespace std;

#define N 205
#define M 40005
#define INF 0x7fffffff

#define min(a,b) a < b ?  a : b
#define CLR(a,v) memset(a,v,sizeof(a))

struct Vertex
{
    int head;
}V[N];

struct Edge
{
    int v,c,f,next;
    Edge(){}
    Edge(int v,int c,int f,int ne):v(v),c(c),f(f),next(ne){}
}E[M];

int d[N],pre[N],cur[N],gap[N];

int top,s,t,n;

void Init()
{
    top = 0;
    CLR(V,-1);
}

void Add_edge(int u,int v,int c)
{
    E[top] = Edge(v,c,0,V[u].head);
    V[u].head = top++;
    E[top] = Edge(u,0,0,V[v].head);
    V[v].head = top++;
}

void set_d()
{
    queue<int> Q;
    CLR(d,-1);
    CLR(gap,0);
    d[t] = 0;
    Q.push(t);
    while(!Q.empty())
    {
        int v = Q.front();
        Q.pop();
        ++gap[ d[v] ];
        for(int i=V[v].head;i!=-1;i=E[i].next)
        {
            int u = E[i].v;
            if(d[u] == -1)
            {
                d[u] = d[v]+1;
                Q.push(u);
            }
        }
    }
}

int Sap()
{
    set_d();                                        //You can replace it with "CLR(d,0)" if you feel it trouble
    int MaxFlow = 0, u = s;
    int flow = INF;
    memcpy(cur,V,sizeof(V));                        //current arc
    while(d[s] < n)
    {
        int &i = cur[u];                            //reference
        for(;i!=-1;i=E[i].next)
        {
            int v = E[i].v;
            if(E[i].c > E[i].f && d[u] == d[v]+1)  //admissible arc
            {
                u = v;
                pre[v] = i;
                flow = min(flow,E[i].c-E[i].f);
                if(u == t)
                {
                    while(u != s)
                    {
                        int j = pre[u];
                        E[j].f   += flow;
                        E[j^1].f -= flow;
                        u = E[j^1].v;
                    }
                    MaxFlow += flow;
                    flow = INF;
                }
                break;
            }
        }
        if(i == -1)                                //there's no admissible arc.
        {
            if(--gap[ d[u] ] == 0)
                break;
            int dmin = n-1;
            cur[u] = V[u].head;
            for(int j=V[u].head;j!=-1;j=E[j].next)
                if(E[j].c > E[j].f)                //not full arc
                    dmin = min(dmin,d[ E[j].v ]);
            d[u] = dmin+1;
            ++gap[ d[u] ];
            if(u != s)
                u = E[ pre[u]^1 ].v;
        }
    }
    return MaxFlow;
}

最小费用最大流。(最小费用路算法)复杂度O(n*m*MaxFlow)。
需要注意的地方:加反向边时,费用为真实费用的负值。
#include <queue>
#include <stdio.h>
#include <string.h>

using namespace std;

#define N 105
#define M 5205
#define INF 0x3fffffff

#define min(a,b) a < b ?  a : b
#define CLR(a,v) memset(a,v,sizeof(a))

struct Vertex
{
    int head;
}V[N];

struct Edge
{
    int v,c,f,cost,next;
    Edge(){}
    Edge(int v,int c,int f,int co,int ne):v(v),c(c),f(f),cost(co),next(ne){}
}E[M];

int pre[N],dis[N];

int top,s,t;

bool in[N];

void Init()
{
    top = 0;
    CLR(V,-1);
}

void Add_edge(int u,int v,int c,int cost)
{
    E[top] = Edge(v,c,0,cost,V[u].head);
    V[u].head = top++;
    E[top] = Edge(u,0,0,-cost,V[v].head);
    V[v].head = top++;
}

bool Spfa()
{
    CLR(dis,63);
    CLR(in,false);
    queue<int> Q;
    Q.push(s);
    dis[s] = 0;
    in[s] = true;
    while(!Q.empty())
    {
        int u = Q.front();
        for(int i=V[u].head;i!=-1;i=E[i].next)
        {
            int v = E[i].v;
            if(dis[u]+E[i].cost < dis[v] && E[i].c > E[i].f)
            {
                dis[v] = dis[u]+E[i].cost;
                pre[v] = i;
                if(!in[v])
                    Q.push(v);
                in[v] = true;
            }
        }
        Q.pop();
        in[u] = false;
    }
    return dis[t] != dis[N-1];
}

int Ford_Fulkerson()
{
    int i,MinCost = 0;
    while(Spfa())
    {
        int flow = INF;
        for(int v=t;v!=s;v=E[i^1].v)
        {
            i = pre[v];
            flow = min(flow,E[i].c-E[i].f);
        }
        for(int v=t;v!=s;v=E[i^1].v)
        {
            i = pre[v];
            E[i].f   += flow;
            E[i^1].f -= flow;
            MinCost += flow * E[i].cost;
        }
    }
    return MinCost;
}




SAP求最大流。复杂度O(n*n*m)。

#include <queue>
#include <stdio.h>
#include <string.h>

using namespace std;

#define N 205
#define M 40005
#define INF 0x7fffffff

#define min(a,b) a < b ?  a : b
#define CLR(a,v) memset(a,v,sizeof(a))

struct Vertex
{
    int head;
}V[N];

struct Edge
{
    int v,c,f,next;
    Edge(){}
    Edge(int v,int c,int f,int ne):v(v),c(c),f(f),next(ne){}
}E[M];

int d[N],pre[N],cur[N],gap[N];

int top,s,t,n;

void Init()
{
    top = 0;
    CLR(V,-1);
}

void Add_edge(int u,int v,int c)
{
    E[top] = Edge(v,c,0,V[u].head);
    V[u].head = top++;
    E[top] = Edge(u,0,0,V[v].head);
    V[v].head = top++;
}

void set_d()
{
    queue<int> Q;
    CLR(d,-1);
    CLR(gap,0);
    d[t] = 0;
    Q.push(t);
    while(!Q.empty())
    {
        int v = Q.front();
        Q.pop();
        ++gap[ d[v] ];
        for(int i=V[v].head;i!=-1;i=E[i].next)
        {
            int u = E[i].v;
            if(d[u] == -1)
            {
                d[u] = d[v]+1;
                Q.push(u);
            }
        }
    }
}

int Sap()
{
    set_d();                                        //You can replace it with "CLR(d,0)" if you feel it trouble
    int MaxFlow = 0, u = s;
    int flow = INF;
    memcpy(cur,V,sizeof(V));                        //current arc
    while(d[s] < n)
    {
        int &i = cur[u];                            //reference
        for(;i!=-1;i=E[i].next)
        {
            int v = E[i].v;
            if(E[i].c > E[i].f && d[u] == d[v]+1)  //admissible arc
            {
                u = v;
                pre[v] = i;
                flow = min(flow,E[i].c-E[i].f);
                if(u == t)
                {
                    while(u != s)
                    {
                        int j = pre[u];
                        E[j].f   += flow;
                        E[j^1].f -= flow;
                        u = E[j^1].v;
                    }
                    MaxFlow += flow;
                    flow = INF;
                }
                break;
            }
        }
        if(i == -1)                                //there's no admissible arc.
        {
            if(--gap[ d[u] ] == 0)
                break;
            int dmin = n-1;
            cur[u] = V[u].head;
            for(int j=V[u].head;j!=-1;j=E[j].next)
                if(E[j].c > E[j].f)                //not full arc
                    dmin = min(dmin,d[ E[j].v ]);
            d[u] = dmin+1;
            ++gap[ d[u] ];
            if(u != s)
                u = E[ pre[u]^1 ].v;
        }
    }
    return MaxFlow;
}


最小费用最大流。(最小费用路算法)复杂度O(n*m*MaxFlow)。

需要注意的地方:加反向边时,费用为真实费用的负值。

#include <queue>
#include <stdio.h>
#include <string.h>

using namespace std;

#define N 105
#define M 5205
#define INF 0x3fffffff

#define min(a,b) a < b ?  a : b
#define CLR(a,v) memset(a,v,sizeof(a))

struct Vertex
{
    int head;
}V[N];

struct Edge
{
    int v,c,f,cost,next;
    Edge(){}
    Edge(int v,int c,int f,int co,int ne):v(v),c(c),f(f),cost(co),next(ne){}
}E[M];

int pre[N],dis[N];

int top,s,t;

bool in[N];

void Init()
{
    top = 0;
    CLR(V,-1);
}

void Add_edge(int u,int v,int c,int cost)
{
    E[top] = Edge(v,c,0,cost,V[u].head);
    V[u].head = top++;
    E[top] = Edge(u,0,0,-cost,V[v].head);
    V[v].head = top++;
}

bool Spfa()
{
    CLR(dis,63);
    CLR(in,false);
    queue<int> Q;
    Q.push(s);
    dis[s] = 0;
    in[s] = true;
    while(!Q.empty())
    {
        int u = Q.front();
        for(int i=V[u].head;i!=-1;i=E[i].next)
        {
            int v = E[i].v;
            if(dis[u]+E[i].cost < dis[v] && E[i].c > E[i].f)
            {
                dis[v] = dis[u]+E[i].cost;
                pre[v] = i;
                if(!in[v])
                    Q.push(v);
                in[v] = true;
            }
        }
        Q.pop();
        in[u] = false;
    }
    return dis[t] != dis[N-1];
}

int Ford_Fulkerson()
{
    int i,MinCost = 0;
    while(Spfa())
    {
        int flow = INF;
        for(int v=t;v!=s;v=E[i^1].v)
        {
            i = pre[v];
            flow = min(flow,E[i].c-E[i].f);
        }
        for(int v=t;v!=s;v=E[i^1].v)
        {
            i = pre[v];
            E[i].f   += flow;
            E[i^1].f -= flow;
            MinCost += flow * E[i].cost;
        }
    }
    return MinCost;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值