1. 程式人生 > >網絡流之最大流-Ford-Fullkerson算法 DFS && BFS

網絡流之最大流-Ford-Fullkerson算法 DFS && BFS

global log cap {} lse scan bae Go tor

理解處

刷題處

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