一个国家,有n座城市,编号为1~n,有n-1条有向边

如果不考虑边的有向性,这n个城市刚好构成一棵树

现在国王要在这n个城市中选择一个作为首都

要求:从首都可以到达这个国家的任何一个城市(边是有向的)

所以一个城市作为首都,可能会有若干边需要改变方向

现在问,选择哪些城市作为首都,需要改变方向的边最少。

输出最少需要改变方向的边数

输出可以作为首都的编号

树形DP

先假定城市1作为首都

令tree(i)表示以i为根的子树

dp[i]表示在tree(i)中,若以i为首都的话,需要改变的边数

第一次dfs,求出dp数组

ans[i]表示在整棵树中,若以i为首都的话,需要改变的边数(注意和dp数组的意义的区别)

明显:ans[1]=dp[1]

明显有:

在一棵有向树中,若首都为u,现在我们要让u的儿子节点v为首都,只需要改变1条边的方向

假设节点u是节点v的父节点,e=(u,v),ans[u]已知

若e的方向指向v,则:ans[v]=ans[u]+1

否则:ans[v]=ans[u]-1

所以第二次dfs,递推求出ans数组

接着,找出min=min(ans[i]),并输出min

输出所有使得ans[i]==min的i

  1. #include<cstdio>
  2. #include<cstring>
  3.  
  4. using namespace std;
  5.  
  6. const int maxn=+;
  7.  
  8. struct Edge
  9. {
  10. int to,next;
  11. bool flag;
  12. };
  13. Edge edge[maxn<<];
  14. int head[maxn];
  15. int tot;
  16. int ans[maxn];
  17. int dp[maxn];
  18. int print[maxn];
  19.  
  20. void init()
  21. {
  22. memset(head,-,sizeof head);
  23. tot=;
  24. memset(dp,,sizeof dp);
  25. }
  26.  
  27. void addedge(int u,int v,bool flag)
  28. {
  29. edge[tot].to=v;
  30. edge[tot].flag=flag;
  31. edge[tot].next=head[u];
  32. head[u]=tot++;
  33. }
  34.  
  35. void dfs0(int ,int );
  36. void dfs1(int ,int );
  37.  
  38. int main()
  39. {
  40. int n;
  41. init();
  42. bool cnt=true;
  43. scanf("%d",&n);
  44. for(int i=;i<n;i++)
  45. {
  46. int u,v;
  47. scanf("%d %d",&u,&v);
  48. addedge(u,v,cnt);
  49. addedge(v,u,!cnt);
  50. }
  51. dfs0(,-);
  52. ans[]=dp[];
  53. dfs1(,-);
  54.  
  55. int min=ans[];
  56. for(int i=;i<=n;i++)
  57. {
  58. if(ans[i]<min)
  59. min=ans[i];
  60. }
  61. tot=;
  62. for(int i=;i<=n;i++)
  63. {
  64. if(ans[i]==min)
  65. {
  66. print[tot++]=i;
  67. }
  68. }
  69.  
  70. printf("%d\n",min);
  71. for(int i=;i<tot-;i++)
  72. {
  73. printf("%d ",print[i]);
  74. }
  75. printf("%d\n",print[tot-]);
  76.  
  77. return ;
  78. }
  79.  
  80. void dfs0(int u,int pre)
  81. {
  82. for(int i=head[u];~i;i=edge[i].next)
  83. {
  84. int v=edge[i].to;
  85. bool flag=edge[i].flag;
  86. if(v==pre)
  87. continue;
  88. dfs0(v,u);
  89. if(flag)
  90. dp[u]+=dp[v];
  91. else
  92. dp[u]+=(dp[v]+);
  93. }
  94. return ;
  95. }
  96.  
  97. void dfs1(int u,int pre)
  98. {
  99. for(int i=head[u];~i;i=edge[i].next)
  100. {
  101. int v=edge[i].to;
  102. int flag=edge[i].flag;
  103. if(v==pre)
  104. continue;
  105. if(flag)
  106. ans[v]=ans[u]+;
  107. else
  108. ans[v]=ans[u]-;
  109. dfs1(v,u);
  110. }
  111. return ;
  112. }

CF 219D Choosing Capital for Treeland 树形DP 好题的更多相关文章

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

    http://codeforces.com/problemset/problem/219/D 题意 给一颗树但边是单向边,求至少旋转多少条单向边的方向,可以使得树上有一点可以到达树上任意一点,若有多个 ...

  2. CodeForces 219D Choosing Capital for Treeland (树形DP)经典

    <题目链接> 题目大意: 给定一个有向树,现在要你从这颗树上选一个点,使得从这个点出发,到达树上其它所有点所需翻转的边数最小,输出最少需要翻转的边数,并且将这些符合条件的点输出. 解题分析 ...

  3. CF#135 D. Choosing Capital for Treeland 树形DP

    D. Choosing Capital for Treeland 题意 给出一颗有方向的n个节点的树,现在要选择一个点作为首都. 问最少需要翻转多少条边,使得首都可以到所有其他的城市去,以及相应的首都 ...

  4. CF219D. Choosing Capital for Treeland [树形DP]

    D. Choosing Capital for Treeland time limit per test 3 seconds memory limit per test 256 megabytes i ...

  5. [CF] 219D Choosing Capital for Treeland

    题意翻译 题目描述 Treeland国有n个城市,这n个城市连成了一颗树,有n-1条道路连接了所有城市.每条道路只能单向通行.现在政府需要决定选择哪个城市为首都.假如城市i成为了首都,那么为了使首都能 ...

  6. [codeforces219D]Choosing Capital for Treeland树形dp

    题意:给出一棵树,带有向边,找出某个点到达所有点需要反转的最少的边. 解题关键:和求树的直径的思路差不多,将求(父树-子树)的最大值改为求特定值.依然是两次dfs,套路解法. 对树形dp的理解:树形d ...

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

    题目链接:http://codeforces.com/contest/219/problem/D 树dp //#pragma comment(linker, "/STACK:10240000 ...

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

    Choosing Capital for Treeland time limit per test 3 seconds memory limit per test 256 megabytes inpu ...

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

    题目是给一张边有向的树形图.要选出首都的点,首都要都能走到其他点,因此要反转一些边的方向.问可以选哪几个点作为首都,使它们所需反转边的数量最少. 这题挺好想的,因为做过HDU2196. 首先就不妨设正 ...

随机推荐

  1. python程序的调试方法

      [转自:http://blog.csdn.net/luckeryin/article/details/4477233] 本文讨论在没有方便的IDE工具可用的情况下,使用pdb调试python程序 ...

  2. sqlserver模糊查询【转】

    http://blog.csdn.net/liuxinxin1125/article/details/5444873 SELECT * FROM user WHERE name LIKE ';%三%' ...

  3. OpenJudge计算概论-细菌的战争

    /*====================================================================== 细菌的战争 总时间限制: 1000ms 内存限制: 6 ...

  4. OpenJudge计算概论-求满足条件的3位数

    /*======================================================================== 求满足条件的3位数 总时间限制: 1000ms 内 ...

  5. 常用邮件 smtp pop

    常用的邮箱服务器(SMTP.POP3)地址.端口  sina.com: POP3服务器地址:pop3.sina.com.cn(端口:110) SMTP服务器地址:smtp.sina.com.cn(端口 ...

  6. zookeeper源码学习一——zookeeper启动

    最近正在研究zookeeper,一些心得记录一下,如有错误,还请大神指正. zookeeper下载地址:http://zookeeper.apache.org/releases.html,百度一下就能 ...

  7. tomcat如何按站点调试本机程序

    1.配置host host地址:c:\windows\system32\drivers\etc 配置本机域名: # localhost name resolution is handled withi ...

  8. ORA-27086: unable to lock file - already in use

    问题现象: SQL> startup ORACLE instance started. Total System Global Area 1854021632 bytes Fixed Size  ...

  9. windows 下svn 创建分支 合并分支 冲突

    我用的系统是win7+Subversion 1.7.4.服务器搭建就略过了,我也是从网上找的,基本上就是几个命令吧!我用的CentOs6.5 .网上找了几个命令搭建很快,基本上是: 1.# sudo  ...

  10. ios9 URL Schemes列为白名单,才可正常检查其他应用是否安装

    http://my.oschina.net/u/1244672/blog/512210 如果你在模拟器上运行可以能还会有以下报错: -canOpenURL: failed for URL: “weix ...