377D

树形dp

就是求每个点到标记的点的最大距离 一个经典模型

有一个巧妙的方法,我们求出以这些关键点的直径,然后每个点到关键点的最大距离就是到直径两端的距离

#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, m, d, root, ans, x;
int mark[N], d1[N], d2[N];
vector<int> G[N];
void dfs(int u, int last, int *d)
{
    for(int i = 0; i < G[u].size(); ++i)
    {
        int v = G[u][i];
        if(v == last) continue;
        d[v] = d[u] + 1;
        dfs(v, u, d);
    }
}
int main()
{
    scanf("%d%d%d", &n, &m, &d);    
    for(int i = 1; i <= m; ++i) scanf("%d", &x), mark[x] = 1;
    for(int i = 1; i < n; ++i)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1, 0, d1);
    for(int i = 1; i <= n; ++i) if(d1[i] > d1[root] && mark[i]) root = i;
    d1[root] = 0;
    dfs(root, 0, d1);
    root = 0;
    for(int i = 1; i <= n; ++i) if(d1[i] > d1[root] && mark[i]) root = i;
    dfs(root, 0, d2);
    for(int i = 1; i <= n; ++i) if(d1[i] <= d && d2[i] <= d) ++ans;
    cout << ans;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/19992147orz/p/7597348.html