一.题目描述
NC571寻找牛妹
n个结点之间有n-1条边,有一个目标数组X,其中有m个目标结点,从根结点走到每个目标结点Xi,每条边最多可以走两次,问从根结点走到每一个目标节点最多可以经过几条边?
二.算法(暴力搜索)
图片说明
首先我们要理解题意,但对于n个节点之间有n-1条边我们可以认为其是一个树,由于其连通性我们可以做出如下分析:
图片说明 ,下面我们利用暴力搜索来解决,下面给出完整代码:

class Solution {
public:
    int num[200005];//记录孩子个数(并不是一层而是下方全部)
    int dis[200005];//记录距离
    vector<int>mp[200005];
    vector<int> solve(int n, int m, vector<int>& u, vector<int>& v, vector<int>& x) {
        for(int i=0;i<n-1;i++){
            //记录双向边
            mp[u[i]].push_back(v[i]);
            mp[v[i]].push_back(u[i]);
        }
        vector<int>cn(m);
        int ans=2*(u.size()-1);
        dfs(1,0,0);
        for(int i=0;i<m;i++){
            //利用前面推导公式计算
            cn[i]=ans-dis[x[i]]-2*(num[x[i]]-1);
        }
        return cn;
    }
    int dfs(int now,int pre,int cn){
        //now表示当前搜索结点,pre表示前一次搜索的节点,cn表示当前结点到根结点的距离
        dis[now]=cn;
        int sum=0;
        for(auto &j:mp[now]){
            if(j!=pre){
                sum+=dfs(j,now,cn+1)+1;
            }
        }
        num[now]=sum;
        return sum;
    }
};

时间复杂度: 对于每一个节点只有一次访问
空间复杂度: 利用了二维vector来存图
优缺点:代码实现简单,但是利用的公式推导难理解
三.算法(java实现)
可以利用java的ArrayList来代替c++的vector来实现,思路相同,下面是完整代码:

import java.util.*;
public class Solution {
    ArrayList<Integer>[]mp;
    int[]dis;
    int[]num;
    public int[] solve (int n, int m, int[] u, int[] v, int[] x) {
        //对数组和ArrList分配空间
        mp=new ArrayList[n+1];
        dis=new int[n+1];
        num=new int[n+1];
        int[]cn=new int[m];
        for(int i=1;i<=n;i++){
            mp[i]=new ArrayList<>();
        }
        for(int i=0;i<n-1;i++){
            //双向边
            mp[u[i]].add(v[i]);
            mp[v[i]].add(u[i]);
        }
        dfs(1,0,0);

        int sum=2*(u.length-1);
        for(int i=0;i<m;i++){
            //利用推导公式
            cn[i]=sum-dis[x[i]]-(num[x[i]]-1)*2;
        }
        return cn;
    }
    int dfs(int now,int pre,int cn){
        //now表示当前搜索结点,pre表示前一次搜索的节点,cn表示当前结点到根结点的距离
        dis[now]=cn;
        int cnt=0;
        for(int j:mp[now]){
            if(j!=pre){
                cnt+=dfs(j,now,cn+1)+1;
            }

        }
        num[now]=cnt;
        return cnt;
    }
}

时间复杂度: 对于每一个节点只有一次访问
空间复杂度: 利用了ArrayList二维来存图
优缺点:代码实现简单,但是利用的公式推导难理解