标签:
1 /*
2 题意:求一个点为根节点,使得到其他所有点的距离最短,是有向边,反向的距离+1
3 树形DP:首先假设1为根节点,自下而上计算dp[1](根节点到其他点的距离),然后再从1开始,自上而下计算dp[v],
4 此时可以从上个节点的信息递推出来
5 */
6 #include <cstdio>
7 #include <cstring>
8 #include <cmath>
9 #include <vector>
10 using namespace std;
11
12 const int MAXN = 2e5 + 10;
13 const int INF = 0x3f3f3f3f;
14 struct Edge {
15 int v, w;
16 };
17 vector<Edge> G[MAXN];
18 int dp[MAXN];
19 bool vis[MAXN];
20 int n, res;
21
22 void DFS(int u) {
23 vis[u] = true;
24 for (int i=0; i<G[u].size (); ++i) {
25 int v = G[u][i].v, w = G[u][i].w;
26 if (vis[v]) continue;
27 DFS (v);
28 res += w;
29 }
30 }
31
32 void DFS2(int u) {
33 vis[u] = true;
34 for (int i=0; i<G[u].size (); ++i) {
35 int v = G[u][i].v, w = G[u][i].w;
36 if (vis[v]) continue;
37 if (w == 0) dp[v] = dp[u] + 1;
38 else dp[v] = dp[u] - 1;
39 DFS2 (v);
40 }
41 }
42
43 void work(void) {
44 memset (vis, false, sizeof (vis));
45 memset (dp, 0, sizeof (dp));
46
47 res = 0; DFS (1); dp[1] = res;
48 memset (vis, false, sizeof (vis));
49 DFS2 (1);
50
51 int mn = INF, p = 0;
52 for (int i=1; i<=n; ++i) {
53 if (mn >= dp[i]) {
54 mn = dp[i]; p = i;
55 }
56 }
57 printf ("%d\n", mn);
58 for (int i=1; i<=n; ++i) {
59 if (i == p) {
60 printf ("%d\n", i); break;
61 }
62 if (dp[i] == mn) printf ("%d ", i);
63 }
64 }
65
66 int main(void) { //Codeforces Round #135 (Div. 2) D. Choosing Capital for Treeland
67 // freopen ("A.in", "r", stdin);
68
69 while (scanf ("%d", &n) == 1) {
70 for (int i=1; i<=n; ++i) G[i].clear ();
71 for (int i=1; i<=n-1; ++i) {
72 int u, v; scanf ("%d%d", &u, &v);
73 G[u].push_back ((Edge) {v, 0});
74 G[v].push_back ((Edge) {u, 1});
75 }
76
77 work ();
78 }
79
80 return 0;
81 }
树形DP Codeforces Round #135 (Div. 2) D. Choosing Capital for Treeland
标签:
原文地址:http://www.cnblogs.com/Running-Time/p/4663538.html