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

问题思考:

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

参考视频:

代码实现:

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

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

 以下是完整代码:

#include <bits/stdc++.h>
using namespace std;

const int INF = 1e9;

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

class Dinic {
public:
    int nodes, src, sink;
    vector<Edge> edges;
    vector<vector<int>> adj;
    vector<int> 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<int> 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<pair<int, int>> 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<string, int> 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;
}

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值