网络流之最大流-Ford-Fullkerson算法 DFS && BFS

Posted shuaihui520

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流之最大流-Ford-Fullkerson算法 DFS && BFS相关的知识,希望对你有一定的参考价值。

理解处

刷题处

DFS

技术分享图片
#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;
const int max_v = 1000;
const int INF = 0x3f3f3f3f;

struct edge
{
    int to,cap,rev;   //rev是反向边的编号,即这条反向边是以to为起点的第几条边
};

vector<edge> G[max_v];
bool used[max_v];
void add(int from,int to,int cap)
{
    G[from].push_back((edge){to,cap,G[to].size()});//因为下一步要加一条反向边,所以不需要-1
    G[to].push_back((edge){from,0,G[from].size()-1});
}
int dfs(int v,int t,int f)
{
    if(v==t) return f;
    used[v]=1;
    for(int i =0;i<G[v].size();++i)
    {
        edge &e = G[v][i];
        if(!used[e.to] && e.cap > 0)
        {
            int d = dfs(e.to,t,min(f,e.cap));
            if(d>0)
            {
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;//给上一层的d,让上一层也能更新;
            }
        }
    }
    return 0;
}

int  main()
{
    int m,s,t;
    scanf("%d%d%d",&s,&t,&m);

    int from,to,cap;
    for(int i=0;i<m;++i)
    {
        //点从1号开始。
        scanf("%d%d%d",&from,&to,&cap);
        add(from,to,cap);

    }

    int flow=0;
    while(1)
    {
        memset(used,0,sizeof(used));
        int f=dfs(s,t,INF);
        if(f==0) break;
        flow+=f;
    }
    printf("%d",flow);


    return 0;
}

/*
1 4 7
1 2 10
1 5 2
2 5 6
2 3 6
3 4 8
3 5 3
5 4 5
结果:11
*/
View Code

 BFS(优化)

技术分享图片
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

const int maxn = 1000001;
const int INF = 0x3f3f3f;
struct no
{
    int to;
    int cap;
    int rev;
};
vector<no> G[maxn];
int level[maxn];///顶点到源点的距离标记
int iter[maxn];///当前弧,在其之前的边没有用了

void add(int from,int to,int cap)
{
    G[from].push_back((no){to,cap,G[to].size()});
    G[to].push_back((no){from,0,G[from].size()-1});
}

void bfs(int s)
{
    memset(level,-1,sizeof(level));
    queue<int> que;
    level[s] = 0;
    que.push(s);
    while(!que.empty())
    {
        int v = que.front( ) ; que.pop( );
        for(int i=0 ; i<G[v].size( ) ; i++)
        {
            no &e = G[v][i];
            if(e.cap>0&&level[e.to]<0)
            {
                level[e.to] = level[v]+1;
                que.push(e.to);
            }
        }
    }
}
int dfs(int v,int t, int f)
{
    if(v==t) return f;

    for(int &i=iter[v];i<G[v].size();++i)//这里是引用,i++的同时iter也++,其实相当于上个的used,不过不用判断了
    {
        no &e = G[v][i];
        if(e.cap>0 && level[e.to]>level[v])
        {
            int d=dfs(e.to,t,min(e.cap,f));
            if(d>0)
            {
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}
int max_flow(int s,int t)
{
    int flow = 0;
    for( ; ; )
    {
        bfs(s);
        if(level[t]<0)
        return flow;
        memset(iter,0,sizeof(iter));
        int f;
        while((f=dfs(s,t,INF))>0)
            flow+=f;
    }
}
int main()
{
    int s,t,m,n;
    scanf("%d%d%d%d",&n,&m,&s,&t);

    int u,v,cap;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&u,&v,&cap);
        add(u,v,cap);
    }

    printf("%d",max_flow(s,t));
    return 0;
}
View Code

 神奇代码:巨快

技术分享图片
#include <bits/stdc++.h>

const int MAXN = 1e6 + 10;
const int INF = 0x3f3f3f3f;

struct Node {
    int v, f, index;
    Node(int v, int f, int index) : v(v), f(f), index(index) {}
};

int n, m, s, t;
std::vector<Node> edge[MAXN];
std::vector<int> list[MAXN], height, count, que, excess;
typedef std::list<int> List;
std::vector<List::iterator> iter;
List dlist[MAXN];
int highest, highestActive;
typedef std::vector<Node>::iterator Iterator;

 void init()
{
    for(int i=0; i<=n; i++)
        edge[i].clear();
}

 void addEdge(const int u, const int v, const int f) {
    edge[u].push_back(Node(v, f, edge[v].size()));
    edge[v].push_back(Node(u, 0, edge[u].size() - 1));
}

 void globalRelabel(int n, int t) {
    height.assign(n, n);
    height[t] = 0;
    count.assign(n, 0);
    que.clear();
    que.resize(n + 1);
    int qh = 0, qt = 0;
    for (que[qt++] = t; qh < qt;) {
        int u = que[qh++], h = height[u] + 1;
        for (Iterator p = edge[u].begin(); p != edge[u].end(); ++p) {
            if (height[p->v] == n && edge[p->v][p->index].f > 0) {
                count[height[p->v] = h]++;
                que[qt++] = p->v;
            }
        }
    }
    for (int i = 0; i <= n; i++) {
        list[i].clear();
        dlist[i].clear();
    }
    for (int u = 0; u < n; ++u) {
        if (height[u] < n) {
            iter[u] = dlist[height[u]].insert(dlist[height[u]].begin(), u);
            if (excess[u] > 0) list[height[u]].push_back(u);
        }
    }
    highest = (highestActive = height[que[qt - 1]]);
}
 void push(int u, Node &e) {
    int v = e.v;
    int df = std::min(excess[u], e.f);
    e.f -= df;
    edge[v][e.index].f += df;
    excess[u] -= df;
    excess[v] += df;
    if (0 < excess[v] && excess[v] <= df) list[height[v]].push_back(v);
}

 void discharge(int n, int u) {
    int nh = n;
    for (Iterator p = edge[u].begin(); p != edge[u].end(); ++p) {
        if (p->f > 0) {
            if (height[u] == height[p->v] + 1) {
                push(u, *p);
                if (excess[u] == 0) return;
            } else {
                nh = std::min(nh, height[p->v] + 1);
            }
        }
    }
    int h = height[u];
    if (count[h] == 1) {
        for (int i = h; i <= highest; i++) {
            for (List::iterator it = dlist[i].begin(); it != dlist[i].end();
                 ++it) {
                count[height[*it]]--;
                height[*it] = n;
            }
            dlist[i].clear();
        }
        highest = h - 1;
    } else {
        count[h]--;
        iter[u] = dlist[h].erase(iter[u]);
        height[u] = nh;
        if (nh == n) return;
        count[nh]++;
        iter[u] = dlist[nh].insert(dlist[nh].begin(), u);
        highest = std::max(highest, highestActive = nh);
        list[nh].push_back(u);
    }
}

 int hlpp(int n, int s, int t) {
    if (s == t) return 0;
    highestActive = 0;
    highest = 0;
    height.assign(n, 0);
    height[s] = n;
    iter.resize(n);
    for (int i = 0; i < n; i++)
        if (i != s)
            iter[i] = dlist[height[i]].insert(dlist[height[i]].begin(), i);
    count.assign(n, 0);
    count[0] = n - 1;
    excess.assign(n, 0);
    excess[s] = INF;
    excess[t] = -INF;
    for (int i = 0; i < (int)edge[s].size(); i++) push(s, edge[s][i]);
    globalRelabel(n, t);
    for (int u /*, res = n*/; highestActive >= 0;) {
        if (list[highestActive].empty()) {
            highestActive--;
            continue;
        }
        u = list[highestActive].back();
        list[highestActive].pop_back();
        discharge(n, u);
        // if (--res == 0) globalRelabel(res = n, t);
    }
    return excess[t] + INF;
}

int main() {
    while(~scanf("%d %d %d %d", &n, &m, &s, &t)){
        init();
        for (int i = 0, u, v, f; i < m; i++) {
            scanf("%d %d %d", &u, &v, &f);
            addEdge(u, v, f);
        }
        printf("%d", hlpp(n + 1, s, t));///点是1~n范围的话,貌似要 n+1
    }
    return 0;
}
View Code

 

以上是关于网络流之最大流-Ford-Fullkerson算法 DFS && BFS的主要内容,如果未能解决你的问题,请参考以下文章

网络流:最大流之SAP算法

网络流之最大流算法

网络流最大流之Dinic算法

网络流之最大流

线性规划网络流之最短增广路算法

网络流之最大流