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

题目是给一张边有向的树形图。要选出首都的点,首都要都能走到其他点,因此要反转一些边的方向。问可以选哪几个点作为首都,使它们所需反转边的数量最少。

这题挺好想的,因为做过HDU2196

  • 首先就不妨设正向边权值为0,反向边权值为1,那样就是各个点出发到其他点经过边所需的最少权值和。
  • 然后对于每个点,分两个部分考虑:以这个点为根的子树这个点往上走的部分
    1. dp[0][u]表示以u点作为首都且以u点为根的子树部分所需反转边的数量,容易知道就等于子树内边权和
    2. dp[1][u]表示以u点作为首都且u点向上部分所需反转边的数量,画下图就知道怎么转移了:dp[1][v] = ( dp[0][u]-dp[0][v]-weight(u,v) ) + dp[1][u] + weight(v,u) (v是u的孩子)
  • 这样最后对于每个点u,它的答案就是这两部分之和了,即dp[0][u]+dp[1][u]。

感觉又学到一种树形DP的新姿势:分别考虑点往下的子树和点往上的父亲部分。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define INF (1<<30)
 6 #define MAXN 222222
 7 struct Edge{
 8     int u,v,w,next;
 9 }edge[MAXN<<1];
10 int NE,head[MAXN];
11 void addEdge(int u,int v,int w){
12     edge[NE].u=u; edge[NE].v=v; edge[NE].w=w;
13     edge[NE].next=head[u]; head[u]=NE++;
14 }
15 int d[2][MAXN];
16 void dfs0(int u,int fa){
17     for(int i=head[u]; i!=-1; i=edge[i].next){
18         int v=edge[i].v;
19         if(v==fa) continue;
20         dfs0(v,u);
21         d[0][u]+=d[0][v]+edge[i].w;
22     }
23 }
24 void dfs1(int u,int fa){
25     for(int i=head[u]; i!=-1; i=edge[i].next){
26         int v=edge[i].v;
27         if(v==fa) continue;
28         d[1][v]=d[0][u]-d[0][v]-edge[i].w+d[1][u]+edge[i^1].w;
29         dfs1(v,u);
30     }
31 }
32 int main(){
33     memset(head,-1,sizeof(head));
34     int n,a,b;
35     scanf("%d",&n);
36     for(int i=1; i<n; ++i){
37         scanf("%d%d",&a,&b);
38         addEdge(a,b,0); addEdge(b,a,1);
39     }
40     dfs0(1,1);
41     dfs1(1,1);
42     int res=INF;
43     for(int i=1; i<=n; ++i) res=min(res,d[0][i]+d[1][i]);
44     printf("%d\n",res);
45     for(int i=1; i<=n; ++i){
46         if(res==d[0][i]+d[1][i]){
47             printf("%d ",i);
48         }
49     }
50     return 0;
51 }
时间: 2024-12-18 07:04:45

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

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 (树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&

(纪念第一道完全自己想的树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 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 详情见代码,这道

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

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

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

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