力扣每日一题:2646. 最小化旅行的价格总和(2023-12-06)
力扣每日一题
题目:2646. 最小化旅行的价格总和
日期:2023-12-06
用时:30 m 14 s
时间:8ms
内存:42.98MB
思路:先统计旅行中每个节点路过的次数(dfs方法),再计算减半后的价格之和的最小值(dp方法),最后比较下减半和未减半的价格。dp方法中,对于相邻的父子节点有两种情况:
- 如果父节点价格不变,那么子节点的价格取减半和不变两种情况的最小值
- 如果父节点价格减半,那么子节点的价格只能不变
代码:每条路上通过的城市数量实际就是图中每个节点的子节点数量。
class Solution {
public int minimumTotalPrice(int n, int[][] edges, int[] price, int[][] trips) {
list = new ArrayList[n];
for(int i=0;i<n;i++){
list[i] = new ArrayList<>();
}
for(int[] edge:edges){
list[edge[0]].add(edge[1]);
list[edge[1]].add(edge[0]);
}
cnt = new int[n];
for(int[] trip:trips){
end = trip[1];
dfs(trip[0],-1);
}
int[] res = dp(0,-1,price);
return Math.min(res[0],res[1]);
}
List<Integer>[] list;
int end;
int[] cnt;
boolean dfs(int x, int fa) {
if (x == end) {
cnt[x]++;
return true;
}
for (int y : list[x]) {
if (y != fa && dfs(y, x)) {
cnt[x]++;
return true;
}
}
return false;
}
int[] dp(int index,int target,int[] price){
int prices = price[index]*cnt[index];
int halfPrices = prices/2;
for(int num:list[index]){
if(num!=target){
int[] res = dp(num,index,price);
prices += Math.min(res[0],res[1]);
halfPrices += res[0];
}
}
return new int[]{prices,halfPrices};
}
}