【PAT顶级】1003 Universal Travel Sites(35)[网络最大流,非递归dfs]

【PAT顶级】1003 Universal Travel Sites(35)[网络最大流,非递归dfs]_第1张图片

【PAT顶级】1003 Universal Travel Sites(35)[网络最大流,非递归dfs]_第2张图片

问题思考:

  •  问空间站的容量应该是多少,可以等价于最大流问题。即空间站的容量应该等于网络的最大流。

参考视频:

  • 13-1: 网络流问题基础 Network Flow Problems

代码实现:

  • 我用GPT帮我写了一段 Dinic's Algorithm 寻找网络最大流的C++代码。改了一下输入输出,和空间站 id 的映射,提交发现测试节点 3 出现段错误:

【PAT顶级】1003 Universal Travel Sites(35)[网络最大流,非递归dfs]_第3张图片

  • 又让他给出改进的建议:函数递归层数太深,导致程序内存函数栈爆满,采用非递归方式避免了不断调用函数的问题,提交就直接过了。

【PAT顶级】1003 Universal Travel Sites(35)[网络最大流,非递归dfs]_第4张图片

 以下是完整代码:

#include 
using namespace std;

const int INF = 1e9;

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

class Dinic {
public:
    int nodes, src, sink;
    vector edges;
    vector> adj;
    vector level, ptr;

    Dinic(int n, int s, int t) : nodes(n), src(s), sink(t), adj(n), level(n, -1), ptr(n) {}

    void addEdge(int from, int to, int capacity) {
        edges.push_back({from, to, capacity, 0});
        edges.push_back({to, from, 0, 0});
        adj[from].push_back(edges.size() - 2);
        adj[to].push_back(edges.size() - 1);
    }

    bool bfs() {
        fill(level.begin(), level.end(), -1);
        level[src] = 0;
        queue q;
        q.push(src);

        while (!q.empty()) {
            int current = q.front();
            q.pop();

            for (int id : adj[current]) {
                if (edges[id].capacity - edges[id].flow > 0 && level[edges[id].to] == -1) {
                    level[edges[id].to] = level[current] + 1;
                    q.push(edges[id].to);
                }
            }
        }

        return level[sink] != -1;
    }

    int dfs(int u, int pushed) {
        stack> stk;
        stk.push({u, pushed});

        while (!stk.empty()) {
            int u = stk.top().first;
            int pushed = stk.top().second;
            stk.pop();

            if (pushed == 0) continue;
            if (u == sink) return pushed;

            for (int& cid = ptr[u]; cid < adj[u].size(); cid++) {
                int id = adj[u][cid];
                int v = edges[id].to;

                if (level[u] + 1 == level[v] && edges[id].capacity - edges[id].flow > 0) {
                    int flow = min(pushed, edges[id].capacity - edges[id].flow);
                    int pushed_flow = dfs(v, flow);
                    if (pushed_flow > 0) {
                        edges[id].flow += pushed_flow;
                        edges[id ^ 1].flow -= pushed_flow;
                        return pushed_flow;
                    }
                }
            }
        }

        return 0;
    }

    int maxFlow() {
        int flow = 0;
        while (bfs()) {
            fill(ptr.begin(), ptr.end(), 0);
            while (int pushed = dfs(src, INF)) {
                flow += pushed;
            }
        }
        return flow;
    }
};

int main() {
    int nodes;
    string src, sink;
    cin >> src >> sink >> nodes;
    
    // Note: You might need to adjust the maximum size of the nodes.
    const int MAX_NODES = 10005;
    unordered_map M;
    int cnt = 0;

    auto mark_to_map = [&](string id) {
        if (M.find(id) == M.end())
            M[id] = ++cnt;
    };

    mark_to_map(src);
    mark_to_map(sink);
    Dinic dinic(MAX_NODES, M[src], M[sink]);

    for (int i = 0; i < nodes; i++) {
        string a, b;
        int l;
        cin >> a >> b >> l;
        mark_to_map(a);
        mark_to_map(b);
        dinic.addEdge(M[a], M[b], l);
    }

    int maxFlow = dinic.maxFlow();
    cout << maxFlow << endl;

    return 0;
}

你可能感兴趣的:(代码刷题,深度优先,算法)