zoukankan      html  css  js  c++  java
  • CF 219D Choosing Capital for Treeland 树形DP 好题

    一个国家,有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=200000+5;
      7 
      8 struct Edge
      9 {
     10     int to,next;
     11     bool flag;
     12 };
     13 Edge edge[maxn<<1];
     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,-1,sizeof head);
     23     tot=0;
     24     memset(dp,0,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=1;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(1,-1);
     52     ans[1]=dp[1];
     53     dfs1(1,-1);
     54 
     55     int min=ans[1];
     56     for(int i=2;i<=n;i++)
     57     {
     58         if(ans[i]<min)
     59             min=ans[i];
     60     }
     61     tot=1;
     62     for(int i=1;i<=n;i++)
     63     {
     64         if(ans[i]==min)
     65         {
     66             print[tot++]=i;
     67         }
     68     }
     69 
     70     printf("%d
    ",min);
     71     for(int i=1;i<tot-1;i++)
     72     {
     73         printf("%d ",print[i]);
     74     }
     75     printf("%d
    ",print[tot-1]);
     76 
     77     return 0;
     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]+1);
     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]+1;
    107         else
    108             ans[v]=ans[u]-1;
    109         dfs1(v,u);
    110     }
    111     return ;
    112 }
    View Code
  • 相关阅读:
    简单的模板解析函数
    HTML通过事件传递参数到js 二 event
    HTML通过事件传递参数到js一
    通过this获取当前点击选项相关数据
    LeetCode 20. 有效的括号(Valid Parentheses)
    LeetCode 459. 重复的子字符串(Repeated Substring Pattern)
    LeetCode 14. 最长公共前缀(Longest Common Prefix)
    LeetCode 168. Excel表列名称(Excel Sheet Column Title)
    LeetCode 171. Excel表列序号(Excel Sheet Column Number) 22
    LeetCode 665. 非递减数列(Non-decreasing Array)
  • 原文地址:https://www.cnblogs.com/-maybe/p/4746443.html
Copyright © 2011-2022 走看看