题目概述
本题是一个关于树形数据结构的算法问题,其中涉及无向、无根树的遍历、路径选择以及成本优化。我们需要在给定的树结构中,找到在特定规则下的最小旅行成本。
题目细节
- 树的构造: 由
n
个节点组成,编号从0
到n - 1
,通过给定的edges
数组定义节点之间的连接关系。 - 节点价格: 每个节点都有一个价格,由
price
数组给出。 - 旅行规划:
trips
数组中包含多次旅行的起始和结束节点。 - 成本优化: 在旅行前,可以选择一些非相邻节点减半其价格。
示例分析
示例 1 提供了一种减半选择,从而达到最小总成本 23。这要求我们不仅计算原始路径成本,还要考虑减半优化的可能性。
解题思路
- 最短路径算法: 首先计算在不考虑价格减半的情况下,每次旅行的最低价格总和。这可以通过Dijkstra算法实现,但是如果考虑价格减半的情况,Dijkstra就不一定可以解决问题了,因此,我们先统计每个节点的经过次数,这点可以直接使用
dfs
实现,代码中实现了dfs_calc_cnt
这个函数来完成该任务。 - 价格减半策略: 考虑价格减半,我们应该选择减少那些能节省最多费用的节点,由于不能给相邻的节点同时进行价格减半,因此我们需要使用动态规划法,实现在较低复杂度下穷举每个节点的减半和不减半的情况下产生的费用。
C++代码实现
class Solution {
public:
inline bool dfs_calc_cnt(int node, int fa, int end, vector<int> &cnt, const vector<vector<int>> &graph) {
if (node == end) {
cnt[node]++;
return true;
}// 找到一条合法路径
for (int chi : graph[node]) {
if (chi == fa) continue;
// 如果递归子树返回true,代表可以到达end,是合法的路径。
bool is_right_way = dfs_calc_cnt(chi, node, end, cnt, graph);
if (is_right_way) {
cnt[node]++;
return true;
}
}
return false;
}
int minimumTotalPrice(int n, vector<vector<int>>& edges, vector<int>& price, vector<vector<int>>& trips) {
vector<vector<int>> graph(n);
for (auto &edge : edges) {
int x = edge[0], y = edge[1];
graph[x].push_back(y);
graph[y].push_back(x);
}
vector<int> cnt(n); // 记录各个节点的经过次数
for (auto &trip : trips) {
int start = trip[0], end = trip[1];
dfs_calc_cnt(start, -1, end, cnt, graph);
}
function<pair<int, int>(int, int)> dfs = [&](int node, int fa) -> pair<int, int> {
int not_half = price[node] * cnt[node];
int half = not_half / 2;
for (auto &chi : graph[node]) {
if (chi == fa) continue;
auto [chi_not_half, chi_half] = dfs(chi, node);
not_half += min(chi_not_half, chi_half);
half += chi_not_half; // 因为本节点减半,所以下一个子节点不可减半
}
return {not_half, half};
};
auto [not_half, half] = dfs(0, -1);
return min(not_half, half);
}
};
代码解析
- 建立图结构: 使用
vector<vector<int>>
来表示图的邻接表。 - 统计经过次数: 使用深度优先搜索(DFS)统计每个节点在所有旅行中的经过次数。
- 成本计算: 分别计算每个节点在减半和不减半情况下的成本,并递归地计算整棵树的最小成本。
总结
此问题的解决方案不仅要求熟练掌握树的遍历算法,还要对动态规划有深入的理解。本文通过详细解释并展示C++代码实现,提供了一个清晰的解题路径。
注意: 本博客旨在提供算法问题的解决思路和示例代码,实际应用时需根据具体情况进行调整。