# 2467. Most Profitable Path in a Tree
###### tags: `Leetcode` `Medium` `Graph` `DFS` `Tree`
Link: https://leetcode.com/problems/most-profitable-path-in-a-tree/description/
## 思路
很典型的一道graph题
### 2DFS
alice从node 0到leaf node有很多路可以走 但是bob只有一条路可以走
因此我们可以先从node 0开始dfs 记录每个node的parent node(这样bob就可以顺着parent node往上走即可) 并且记录每个node和node 0的距离
然后顺着bob的路往上走 如果bob到一个点的距离<alice到这个点的的距离 那么这个点的amount在alice经过的时候就会变成0 如果bob到一个点的距离=alice到这个点的距离 那么这个点的amount在alice经过的时候alice只能拿到amount/2
更新完amount之后再从root开始做一遍dfs 就能找到答案
Q: **无向tree**做dfs怎么预防已经访问的节点再被访问?
A: 在dfs的时候传递currnode和parentnode(currnode的parent) 如果nextnode(currnode的neighbor)等于parentnode 就直接跳过
### 1DFS
参考[这里](https://leetcode.com/problems/most-profitable-path-in-a-tree/discuss/2807411/python-one-dfs)
从上至下遍历 每个点的```d0```(the distance from node ```0``` to node ```i```)我们肯定知道,```db```(distance from node ```i``` to node ```bob```)可以透过dfs自己的children知道
## Code
2DFS
```java=
class Solution {
public int mostProfitablePath(int[][] edges, int bob, int[] amount) {
List<List<Integer>> graph = new ArrayList<>();
int n = edges.length+1;
for(int i=0; i<n; i++) graph.add(new ArrayList<>());
for(int[] edge:edges){
graph.get(edge[0]).add(edge[1]);
graph.get(edge[1]).add(edge[0]);
}
int[] par = new int[n];
int[] time = new int[n];
// calculate the dist from 0 to every other node and get the parent node of every node
dfsFrom0(graph, 0, 0, 0, par, time);
// get bob's path
bobPath(bob, 0, par, time, amount);
// find the maximum net income
return dfs(graph, 0, 0, 0, amount);
}
public void bobPath(int bob, int dist, int[] par, int[] time, int[] amount){
if(bob==0) return;
if(dist<time[bob]) amount[bob] = 0;
else if(dist==time[bob]) amount[bob]/=2;
bobPath(par[bob], dist+1, par, time, amount);
}
public void dfsFrom0(List<List<Integer>> graph, int cur, int p, int dist, int[] par, int[] time){
time[cur]=dist;
par[cur]=p;
for(int next:graph.get(cur)){
if(next==p) continue;
dfsFrom0(graph, next, cur, dist+1, par, time);
}
}
public int dfs(List<List<Integer>> graph, int cur, int p, int curNet, int[] amount){
int maxNet = Integer.MIN_VALUE;
for(int next:graph.get(cur)){
if(next==p) continue;
maxNet = Math.max(maxNet, dfs(graph, next, cur, curNet, amount));
}
if(maxNet==Integer.MIN_VALUE) return amount[cur];
else return maxNet+amount[cur];
}
}
```
1DFS
```java=
class Solution {
public int mostProfitablePath(int[][] edges, int bob, int[] amount) {
List<List<Integer>> graph = new ArrayList<>();
int n = edges.length+1;
for(int i=0; i<n; i++) graph.add(new ArrayList<>());
for(int[] edge:edges){
graph.get(edge[0]).add(edge[1]);
graph.get(edge[1]).add(edge[0]);
}
return dfs(graph, 0, 0, 0, bob, amount)[0];
}
public int[] dfs(List<List<Integer>> graph, int cur, int d0, int p, int bob, int[] amount){
int maxChild = Integer.MIN_VALUE;
int db = cur==bob?0:graph.size();
for(int next:graph.get(cur)){
if(next==p) continue;
int[] tmp = dfs(graph, next, d0+1, cur, bob, amount);
maxChild = Math.max(maxChild, tmp[0]);
db = Math.min(db, tmp[1]+1);
}
int curAmount = amount[cur];
if(db<d0) curAmount=0;
else if(db==d0) curAmount/=2;
//cur node is a leaf node
if(maxChild==Integer.MIN_VALUE) return new int[]{curAmount, db};
else return new int[]{curAmount+maxChild, db};
}
}
```