树形DP Codeforces Round #135 (Div. 2) D. Choosing Capital for Treeland

题目传送门

 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 }
时间: 2024-10-12 03:50:54

树形DP Codeforces Round #135 (Div. 2) D. Choosing Capital for Treeland的相关文章

Codeforces Round #135 (Div. 2) D. Choosing Capital for Treeland dfs

D. Choosing Capital for Treeland time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output The country Treeland consists of n cities, some pairs of them are connected with unidirectional roads. Over

树形dp - Codeforces Round #322 (Div. 2) F Zublicanes and Mumocrates

Zublicanes and Mumocrates Problem's Link Mean: 给定一个无向图,需要把这个图分成两部分,使得两部分中边数为1的结点数量相等,最少需要去掉多少条边. analyse: 树形dp. dp[cur][i][j]:当cur为i集合的时候 有j个和i同集合的方案 状态转移方程为: dp[cur][i][j+k] = min{dp[to][i^1][j=(叶子个数-d)]+dp[cur][i][k]+1,dp[to][i][j]+dp[cur][i][k]} c

贪心 Codeforces Round #135 (Div. 2) C. Color Stripe

题目传送门 1 /* 2 贪心:当m == 2时,结果肯定是ABABAB或BABABA,取最小改变量:当m > 2时,当与前一个相等时, 改变一个字母 3 同时不和下一个相等就是最优的解法 4 */ 5 #include <cstdio> 6 #include <cstring> 7 #include <algorithm> 8 using namespace std; 9 10 const int MAXN = 5e5 + 10; 11 const int IN

构造 Codeforces Round #135 (Div. 2) B. Special Offer! Super Price 999 Bourles!

题目传送门 1 /* 2 构造:从大到小构造,每一次都把最后不是9的变为9,p - p MOD 10^k - 1,直到小于最小值. 3 另外,最多len-1次循环 4 */ 5 #include <cstdio> 6 #include <algorithm> 7 #include <cstring> 8 #include <cmath> 9 using namespace std; 10 11 typedef long long ll; 12 const i

DP Codeforces Round #303 (Div. 2) C. Woodcutters

题目传送门 1 /* 2 题意:每棵树给出坐标和高度,可以往左右倒,也可以不倒 3 问最多能砍到多少棵树 4 DP:dp[i][0/1/2] 表示到了第i棵树时,它倒左或右或不动能倒多少棵树 5 分情况讨论,若符合就取最大值更新,线性dp,自己做出来了:) 6 */ 7 #include <cstdio> 8 #include <algorithm> 9 #include <cstring> 10 #include <cmath> 11 #include &

DP Codeforces Round #FF (Div. 1) A. DZY Loves Sequences

题目传送门 /* DP:先用l,r数组记录前缀后缀上升长度,最大值会在三种情况中产生: 1. a[i-1] + 1 < a[i+1],可以改a[i],那么值为l[i-1] + r[i+1] + 1 2. l[i-1] + 1 3. r[i+1] + 1 //修改a[i] */ #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int MAXN =

递推DP Codeforces Round #260 (Div. 1) A. Boredom

题目传送门 1 /* 2 DP:从1到最大值,dp[i][1/0] 选或不选,递推更新最大值 3 */ 4 #include <cstdio> 5 #include <algorithm> 6 #include <cmath> 7 #include <cstring> 8 using namespace std; 9 10 typedef long long ll; 11 const int MAXN = 1e5 + 10; 12 const int INF

DP Codeforces Round #260 (Div. 1) A. Boredom

题目传送门 1 /* 2 题意:选择a[k]然后a[k]-1和a[k]+1的全部删除,得到点数a[k],问最大点数 3 DP:状态转移方程:dp[i] = max (dp[i-1], dp[i-2] + (ll) i * cnt[i]); 4 只和x-1,x-2有关,和顺序无关,x-1不取,x-2取那么累加相同的值,ans = dp[mx] 5 */ 6 #include <cstdio> 7 #include <algorithm> 8 #include <cstring&

数学+DP Codeforces Round #304 (Div. 2) D. Soldier and Number Game

题目传送门 1 /* 2 题意:这题就是求b+1到a的因子个数和. 3 数学+DP:a[i]保存i的最小因子,dp[i] = dp[i/a[i]] +1;再来一个前缀和 4 */ 5 /************************************************ 6 Author :Running_Time 7 Created Time :2015-8-1 14:08:34 8 File Name :B.cpp 9 ******************************