TLE试图使用Dinic算法解决SPOJ上的Fastflow

时间:2019-06-22 18:48:02

标签: c++ algorithm

我一直在尝试使用Dinic算法和C ++在Spoj上解决Fastflow,但是我一直在获得TLE。我想知道是否有什么方法可以改善我的代码,使其不超过时间限制,或者算法是否不够快地完成该任务?我正在使用BFS查找每个节点与源节点的距离,然后使用DFS查找可以从源向接收器发送多少流量。

#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <queue>
#include <cstring>

using namespace std;

struct Edge {
    int from, to, flow, capacity;
    Edge *reverse;
};

static vector<vector<Edge>> nodeEdges(5002, vector<Edge>());

int source, sink, nodes, level[5002];

void add(int u, int v, int c) {
    Edge e1{ u, v, 0, c };
    Edge e2{ v, u, 0, c };
    e1.reverse = &e2;
    e2.reverse = &e1;
    nodeEdges[u].push_back(e1);
    nodeEdges[v].push_back(e2);
}

bool bfs() {
    int s, t, u, v;
    memset(level, -1, sizeof(int)*(nodes+1));
    level[source] = 0;
    s = 0;
    t = 0;
    queue<int> q;
    q.push(source);
    while (!q.empty()) {
        u = q.front();
        q.pop();
        for (int i = 0; i < nodeEdges[u].size(); i++) {
            v = nodeEdges[u][i].to;
            if (nodeEdges[u][i].flow < nodeEdges[u][i].capacity && level[v] == -1) {
                level[v] = level[u] + 1;
                q.push(v);
            }
        }
    }
    if (level[sink] == -1) {
        return false;
    }
    return true;
}

long long dfs(int u, int fl) {
    if (u == sink) return fl;
    int v;
    long long pushed;
    for (int i = 0; i < nodeEdges[u].size(); i++) {
        v = nodeEdges[u][i].to;
        if (nodeEdges[u][i].flow < nodeEdges[u][i].capacity && level[v] == level[u] + 1) {
            pushed = dfs(v, min(nodeEdges[u][i].capacity - nodeEdges[u][i].flow, fl));
            if (pushed > 0) {
                nodeEdges[u][i].flow += pushed;
                nodeEdges[u][i].reverse->flow -= pushed;
                return pushed;
            }
        }
    }
    return 0;
}

long long solve() {
    long long ret = 0;
    long long flow;
    while (bfs()) {
        while (true) {
            flow = dfs(source, INT32_MAX);
            if (flow) {
                ret += flow;
            }
            else break;
        }
    }
    return ret;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n, m, a, b, c;
    cin >> n >> m;
    source = 1;
    sink = n;
    nodes = n;
    for (int i = 0; i < m; i++) {
        cin >> a >> b >> c;
        if (a != b) {
            add(a, b, c);
        }
    }
    cout << solve();
    return 0;
}

1 个答案:

答案 0 :(得分:1)

您添加边缘的reverse指针均无效,因为它们指向add局部变量。他们需要指向被添加到nodeEdges[u](或nodeEdges[v])中的节点