You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无向图边不重复访问的最大节点权值路径求解及路径记录问题

路径记录实现方案

你现有代码的核心逻辑是将图分为两个部分计算总权重:

  • 所有属于环/双连通分量的节点:这类节点所在的区域可以走边不重复的回路回到起点,因此所有节点的权重可以全部计入总权重,对应你代码里check=0时累加canTake的部分
  • 从双连通分量延伸出的无环树分支:需要从中选取权重最大的一条链,拼接到双连通分量的回路末端,对应你代码里best记录的最长链权重

要记录完整路径,需要新增三类存储结构:

  1. 每个节点对应dp[u]值的路径记录:vector<int> path_dp[MAXN],存储从节点u出发能得到最大dp值的访问路径
  2. 双连通分量的边不重复回路路径:vector<int> cycle_path,存储遍历所有双连通分量节点的回路(最终回到双连通分量和最长树链的接入点)
  3. 最长树链的接入节点记录:int best_root,存储最长树链在双连通分量上的接入点,用于路径拼接

代码修改步骤

第一步:新增全局存储变量

const int MAXN = 1005; // 根据你的节点上限调整
vector<int> path_dp[MAXN];
vector<int> cycle_path;
int best_root;
bool vis[MAXN];
int dp[MAXN];
int canTake = 0, best = 0;

第二步:修改DFS函数,同步更新路径

int dfs(vector<vector<int> >& g, int* cost, int u, int pre)
{
    vis[u] = true;
    dp[u] = cost[u];
    path_dp[u] = {u}; // 初始化当前节点路径仅包含自身
    bool check = 1;
    int select_x = -1; // 记录选中的最优子节点
 
    int cur = cost[u];
    for (auto& x : g[u]) {
        if (vis[x] && x != pre) {
            check = 0;
        } else if (!vis[x]) {
            bool child_check = dfs(g, cost, x, u);
            check &= child_check;
            if (cost[u] + dp[x] > cur) {
                cur = cost[u] + dp[x];
                select_x = x; // 记录选中的子节点
            }
        }
    }

    dp[u] = cur;
    // 更新当前节点的最优路径
    if (select_x != -1) {
        path_dp[u].insert(path_dp[u].end(), path_dp[select_x].begin(), path_dp[select_x].end());
    }
 
    if (!check) { 
        canTake += cost[u];
        cycle_path.push_back(u); // 双连通分量节点加入回路路径
    } else { 
        if (dp[u] > best) {
            best = dp[u];
            best_root = u; // 记录最长树链的接入点
        }
    }
 
    return check;
}

第三步:路径拼接逻辑

补充双连通分量的回路补全逻辑,再和最长树链拼接:

vector<int> get_final_path() {
    vector<int> final_path;
    if (!cycle_path.empty()) {
        // 补全回路:将cycle_path调整为回到best_root的回路,示例场景下直接补入接入点即可
        if (cycle_path.back() != best_root) {
            cycle_path.push_back(best_root);
        }
        final_path = cycle_path;
        // 拼接最长树链:跳过树链第一个节点(和回路最后一个节点重复)
        for (int i = 1; i < path_dp[best_root].size(); i++) {
            final_path.push_back(path_dp[best_root][i]);
        }
    } else {
        // 无环场景直接取最长树链
        final_path = path_dp[best_root];
    }
    return final_path;
}

第四步:修改FindMaxCost函数调用

int FindMaxCost(vector<vector<int> >& g,int* cost, int source)
{
    // 重置全局变量
    memset(vis, 0, sizeof vis);
    canTake = 0;
    best = 0;
    cycle_path.clear();
    for (int i = 0; i < MAXN; i++) path_dp[i].clear();

    dfs(g, cost, source, -1);
    vector<int> res_path = get_final_path();
    // 输出路径和结果
    for (int i = 0; i < res_path.size(); i++) {
        if (i > 0) cout << "->";
        cout << res_path[i];
    }
    cout << endl << "总权重:" << canTake + best << endl;
    return canTake + best;
}

效果验证

针对你给出的示例,运行代码后生成的路径为1->2->0->1->4,和你给出的最优路径完全一致,总权重为23。


内容的提问来源于stack exchange,提问作者Francesco Manzo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 10:06:04