Codeforces 219D. Choosing Capital for Treeland (树dp)

题目链接:http://codeforces.com/contest/219/problem/D

树dp

 1 //#pragma comment(linker, "/STACK:102400000, 102400000")
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <ctime>
10 #include <list>
11 #include <set>
12 #include <map>
13 using namespace std;
14 typedef long long LL;
15 typedef pair <int, int> P;
16 const int N = 2e5 + 5;
17 struct Edge {
18     int next, to, cost;
19 }edge[N << 1];
20 int head[N], tot, d[N], ans1[N], ans[N];
21 int res[N];
22
23 inline void add_edge(int u, int v, int c) {
24     edge[tot].next = head[u];
25     edge[tot].to = v;
26     edge[tot].cost = c;
27     head[u] = tot++;
28 }
29
30 void dfs1(int u, int p) {
31     d[u] = 1;
32     ans1[u] = 0;
33     for(int i = head[u]; ~i; i = edge[i].next) {
34         int v = edge[i].to;
35         if(v == p)
36             continue;
37         dfs1(v, u);
38         d[u] += d[v];
39         ans1[u] += edge[i].cost + ans1[v];
40     }
41 }
42
43 void dfs2(int u, int p) {
44     ans[u] += ans1[u];
45     for(int i = head[u]; ~i; i = edge[i].next) {
46         int v = edge[i].to;
47         if(v == p)
48             continue;
49         ans[v] = ans[u] - ans1[v] - edge[i].cost + !edge[i].cost;
50         dfs2(v, u);
51     }
52 }
53
54 int main()
55 {
56     memset(head, -1, sizeof(head));
57     int n, u, v;
58     scanf("%d", &n);
59     for(int i = 1; i < n; ++i) {
60         scanf("%d %d", &u, &v);
61         add_edge(u, v, 0);
62         add_edge(v, u, 1);
63     }
64     dfs1(1, -1);
65     dfs2(1, -1);
66     int Min = N, cnt = 0;
67     for(int i = 1; i <= n; ++i) {
68         Min = min(Min, ans[i]);
69     }
70     for(int i = 1; i <= n; ++i) {
71         if(ans[i] == Min) {
72             res[++cnt] = i;
73         }
74     }
75     printf("%d\n", Min);
76     sort(res + 1, res + cnt + 1);
77     for(int i = 1; i <= cnt; ++i) {
78         printf("%d%c", res[i], i == cnt ? ‘\n‘: ‘ ‘);
79     }
80     return 0;
81 }
时间: 2025-01-05 15:39:07

Codeforces 219D. Choosing Capital for Treeland (树dp)的相关文章

CodeForces 219D.Choosing Capital for Treeland (树形dp)

题目链接: http://codeforces.com/contest/219/problem/D 题意: 给一个n节点的有向无环图,要找一个这样的点:该点到其它n-1要逆转的道路最少,(边<u,v>,如果v要到u去,则要逆转该边方向)如果有多个这样的点,则升序输出所有 思路: 看了三篇博客,挺好的 http://blog.csdn.net/chl_3205/article/details/9284747 http://m.blog.csdn.net/qq_32570675/article/d

(纪念第一道完全自己想的树DP)CodeForces 219D Choosing Capital for Treeland

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. Overall

Codeforces 219D Choosing Capital for Treeland 2次DP

//选择一个根使得变换最少边的方向使得能够到达所有点#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #i

Codeforces 219D Choosing Capital for Treeland(树形DP)

题目是给一张边有向的树形图.要选出首都的点,首都要都能走到其他点,因此要反转一些边的方向.问可以选哪几个点作为首都,使它们所需反转边的数量最少. 这题挺好想的,因为做过HDU2196. 首先就不妨设正向边权值为0,反向边权值为1,那样就是各个点出发到其他点经过边所需的最少权值和. 然后对于每个点,分两个部分考虑:以这个点为根的子树.这个点往上走的部分: dp[0][u]表示以u点作为首都且以u点为根的子树部分所需反转边的数量,容易知道就等于子树内边权和 dp[1][u]表示以u点作为首都且u点向

CodeForces 219D Choosing Capital for Treeland (树形DP)

题意:给一个树形图,n个节点,n-1条有向边,要求选一个节点作为根,使需要改变方向的边的数目最少.并输出所有可能作为根的点. 思路: 先随便一个点进行DFS,计算将每棵子树的边全部往下时,所需要的费用down[i].还是那个点进行DFS,这次就要求答案了,尝试将每个点t作为根,那么以t作为根的总费用=down[t]+父亲这棵子树.down[t]已经在第一次DFS中求出,而父亲这棵子树就不是down[父亲]了,而是down[父亲]-down[t]+w(父亲,t).注:w为边权. 1 #includ

CF 219D Choosing Capital for Treeland 树形DP 好题

一个国家,有n座城市,编号为1~n,有n-1条有向边 如果不考虑边的有向性,这n个城市刚好构成一棵树 现在国王要在这n个城市中选择一个作为首都 要求:从首都可以到达这个国家的任何一个城市(边是有向的) 所以一个城市作为首都,可能会有若干边需要改变方向 现在问,选择哪些城市作为首都,需要改变方向的边最少. 输出最少需要改变方向的边数 输出可以作为首都的编号 树形DP 先假定城市1作为首都 令tree(i)表示以i为根的子树 dp[i]表示在tree(i)中,若以i为首都的话,需要改变的边数 第一次

codeforces:219D. Choosing Capital for Treeland

题目大意:国家由n个城市以及n-1条连接不同城市的道路组成(每条道路都有正向和逆向之分),并且每个城市到另外一个城市都至少存在一条路径.现在议会要决定选一个城市作为首都.当一个城市选为首都时,需要将所有从首都到其它城市的路径上的所有边都是正向的(如果不是正向的则需要颠转道路).求这样的首都,使得需要颠转的道路数目最小. 其中2<=n<=2e5. 首先这显然是一副无向无环连通图(参考我的博客连通图的一些性质).因此从任意一个城市出发到另外一个城市都有唯一一条路径. 为了后面分析的简便,这里记选取

codeforces 219D D. Choosing Capital for Treeland(树形dp)

题目连接: codeforces 219D 题目大意: 给出一棵树,但是它的边是有向边,选择一个城市,问最少调整多少条边的方向能使一个选中城市可以到达所有的点,输出最小的调整的边数,和对应的点. 题目分析: 定义dp[u]为以u为根的子树中要使根都可达,需要调换方向的边的条数. 定义dir[v]记录点v到父亲节点的边的方向. 然后就是将每个点提成根的操作了. dp[u]换成新的定义,以u为根的到达整棵树需要调整的边的条数. dp[u] = dp[p] + dir[u]?1:-1 详情见代码,这道

树形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 name