USACO 4.2.1 iSap + gap優化

關於網絡流的增廣路系列算法有很多種,其中dinic和iSap是時間效率和代碼複雜度平衡上比較優秀的兩種算法,而兩種算法在增廣時的思路基本一致並且iSap算法具有更優的時間效率和程序競賽上的應用範圍爲更廣,同時相比於預流推進代碼實現更加簡單,所以這裏我們介紹iSap算法在網絡流問題當中的應用。
iSap的思想是基於層數這個特別的關鍵字來進行操作的,主要過程是每一次之尋找最短增廣路,然後每次利用殘量網絡更新源點的層數,與dinic類似但又有一些不同之處,在dinic中,每次尋找增廣路以前都要進行一次Bfs浪費了大量的時間,iSap則只是在當前層數出現斷層時才進行更新,並且利用gap優化層數的查詢後能夠達到更高的時間效率。

/*
ID: weiluoj1
LANG: C++11
TASK: ditch
*/
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1000 + 10;

int n, m;
int dis[maxn], gap[maxn], Cur[maxn];
int C[maxn][maxn], f[maxn], pre[maxn], flow;

void Bfs() {
    queue<int> q;
    q.push(n);

    gap[0] = 1;
    while(!q.empty()) {
        int u = q.front(); q.pop();
        for(int i=1; i<=n; i++) 
            if(C[i][u] && !dis[i]) {
                dis[i] = dis[u] + 1;
                gap[dis[i]]++;
                q.push(i);
            }
    }
}
void iSap() {
    int S = 1, T = n, u = S, v, i;

    gap[0] = T; f[S] = inf;
    for(i=1; i<=n; i++) Cur[i] = 1;
    while(dis[S] < T) {
        for(i=Cur[u]; i<=n; i++) 
            if(C[u][i] && dis[i]+1 == dis[u]) break;

        if(i != n+1) {
            Cur[u] = i;
            pre[v = i] = u;
            if(f[u] < C[u][v]) f[v] = f[u]; else f[v] = C[u][v];

            if((u = v) == T) {
                do {
                    C[pre[u]][u] -= f[T];
                    C[u][pre[u]] += f[T];
                    u = pre[u];
                }while(u != S);
                flow += f[T];
            }
        }else {
            if(--gap[dis[u]] == 0) break;

            Cur[u] = 1; dis[u] = T;
            for(i=1; i<=n; i++) 
                if(C[u][i] && dis[i]+1 < dis[u]) dis[u] = dis[i]+1;
            ++gap[dis[u]];
            if(u != S) u = pre[u];
        }
    }
}
int u, v, w;
int main() {
    freopen("ditch.in", "r", stdin);
    freopen("ditch.out", "w", stdout);

    scanf("%d%d", &m, &n);
    for(int i=1; i<=m; i++) {
        scanf("%d%d%d", &u, &v, &w);
        C[u][v] += w;
    }
    Bfs();
    iSap();
    cout << flow << endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章