CF#196B http://codeforces.com/contest/338/problem/B

题意:在一颗树上,给m个点,求到所有m个点距离不超过d的点的个数,所有路径长度为1。

分析:问题转化,就是求一个点是否到离它最远的给定点的距离小于d,

先第一遍dfs1求出以当前节点u为根的子树到子树中离它最远的给定点的距离d1[u],和次远的距离d2[u],

并且记录下最远距离是从哪个son转移过来的,fo[u];

第二遍dfs2求出当前节点从它fa出发能碰到给定点的最远距离up[u],那么对于当前点u,max(d1[u],up[u]),就是u到

所有给定点的最远的距离;

up[]的可以按照dfs的顺序递推求出,假设我们已经求出up[c1],现在求up[c2]

up[c2]表示从c2的fa结点也就是c1那边给定结点(红色圆点)到c2的最远距离

那么up[c2] 由两部分转移过来,一个是原先以c1为根的子树除去c2的分支后的最远距离,这就是为什么要记录最远是从哪个son转移过来

dd = (fo[c1] == c2 ? d2[c1] : d1[c1]);

还有就是up[c1];显然up[c2] = max(dd,up[c1])+1;(up[c1]表示从c6那边转移过来的值)

树上的DP

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<vector>
 7 #include<cmath>
 8 #define pbk push_back
 9 using namespace std;
10 const int N = 100000+10;
11 const int INF = 1000000+10;
12 vector<int> g[N];
13 int n,m,d;
14 bool p[N];
15 int d1[N],d2[N],fo[N],up[N];
16 int co[N];
17 void update(int c,int rt,int x,int &m1,int &m2) {
18     if (x >= m1) {
19         m2 = m1; m1 = x;
20         fo[rt] = c;
21     }else if (x < m1) {
22         if (x > m2) m2 = x;
23     }
24 }
25 void dfs1(int rt,int fa) {
26     int sz = g[rt].size();
27     d1[rt] = d2[rt] = -INF;
28     for (int i = 0; i < sz; i++) {
29         int c = g[rt][i];
30         if (c == fa) continue;
31         dfs1(c,rt);
32         if (co[c]) {
33             update(c,rt,d1[c]+1,d1[rt],d2[rt]);
34             co[rt] = 1;
35         }
36     }
37     if (p[rt]) {
38         if (d1[rt] > 0 && d2[rt] < 0) d2[rt] = 0;
39         if (d1[rt] < 0) {
40             d1[rt] = 0; fo[rt] = rt;
41         }
42         co[rt] = 1;
43     }
44 }
45 void dfs2(int rt,int fa) {
46     int sz = g[rt].size();
47     for (int i = 0; i < sz; i++) {
48         int c = g[rt][i];
49         if (c == fa) continue;
50         int dd = (fo[rt] == c ? d2[rt] : d1[rt]);
51         up[c] = max(dd, up[rt]) + 1;
52         dfs2(c,rt);
53     }
54 }
55 void solve(){
56     memset(co,0,sizeof(co));
57     memset(fo,-1,sizeof(fo));
58     dfs1(1,-1);
59     up[1] = -INF;
60     dfs2(1,-1);
61   
62     int ans = 0;
63     for (int i = 1; i <= n; i++) {
64         if (d1[i] <= d && up[i] <= d) ans++;
65     }
66     printf("%d\n",ans);
67 }
68 int main(){
69     while (~scanf("%d%d%d",&n,&m,&d)) {
70         memset(p,0,sizeof(p));
71         for (int i = 0; i < m; i++) {
72             int f; scanf("%d",&f);
73             p[f] = 1;
74         }
75         for (int i = 0; i <= n; i++) g[i].clear();
76         for (int i = 0; i < n-1; i++) {
77             int u,v; scanf("%d%d",&u,&v);
78             g[u].pbk(v); g[v].pbk(u);
79         }
80         solve();
81     }
82     return 0;
83 }
View Code

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-06-09
  • 2022-02-06
  • 2022-01-17
  • 2021-12-31
  • 2022-02-05
  • 2022-02-25
猜你喜欢
  • 2022-12-23
  • 2022-01-04
  • 2021-08-08
  • 2022-12-23
  • 2021-12-10
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案