zoukankan      html  css  js  c++  java
  • Codeforces 219D Choosing Capital for Treeland:Tree dp

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

    题意:

      给你一棵树,n个节点。

      树上的边都是有向边,并且不一定是从父亲指向儿子的。

      你可以任意翻转一些边的方向。

      现在让你找一个节点,使得从这个节点出发能够到达其他所有节点,并保证翻转边的数量最小。

      问你最少翻转多少条边,并输出所有满足此条件的节点编号。

    题解:

      本题要解两个dp: dp1 & dp2

      首先考虑dp1:

        表示状态:

          dp1[i]表示使节点i能够到达i的子树中的所有节点,翻转边的最小数量。

        如何转移:

          dp1[i] = ∑ (dp1[son] + 边<i,son>由i指向son ? 0 : 1)

          dfs一遍即可。

      然后求dp2:

        表示状态:

          dp2[i]表示使节点i能够到达这棵树的所有节点,翻转边的最小数量。

        如何转移:

          dp2[i] = dp2[par] + 边<par,i>是否由par指向i ? 1 : -1

          如果边<par,i>由par指向i,那么在dp2[par]中这条边是不会被翻转的,所以此时应该将它翻转,代价+1。

          如果边<par,i>由i指向par,那么在dp2[par]中这条边已经被翻转了一次,然而在dp2[i]中是不需要翻转的,所以将dp2[par]中多余的那次翻转减掉就好。

        边界条件:

          dp2[1] = dp1[1]

          (默认根节点为1)

      所以最终答案为dp2[i]中的最小值,然后将所有dp2[i]等于ans的节点输出就好啦。

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <vector>
     5 #define MAX_N 200005
     6 #define INF 1000000000
     7 
     8 using namespace std;
     9 
    10 struct Edge
    11 {
    12     int dest;
    13     bool flag;
    14     Edge(int _dest,bool _flag)
    15     {
    16         dest=_dest;
    17         flag=_flag;
    18     }
    19     Edge(){}
    20 };
    21 
    22 int n;
    23 int ans=INF;
    24 int dp1[MAX_N];
    25 int dp2[MAX_N];
    26 vector<Edge> edge[MAX_N];
    27 
    28 void read()
    29 {
    30     cin>>n;
    31     int x,y;
    32     for(int i=1;i<n;i++)
    33     {
    34         cin>>x>>y;
    35         edge[x].push_back(Edge(y,true));
    36         edge[y].push_back(Edge(x,false));
    37     }
    38 }
    39 
    40 void dfs1(int now,int p)
    41 {
    42     dp1[now]=0;
    43     for(int i=0;i<edge[now].size();i++)
    44     {
    45         Edge temp=edge[now][i];
    46         if(temp.dest!=p)
    47         {
    48             dfs1(temp.dest,now);
    49             dp1[now]+=dp1[temp.dest]+(!temp.flag);
    50         }
    51     }
    52 }
    53 
    54 void dfs2(int now,int p,bool d)
    55 {
    56     if(now==1) dp2[now]=dp1[now];
    57     else dp2[now]=dp2[p]+(d?1:-1);
    58     ans=min(ans,dp2[now]);
    59     for(int i=0;i<edge[now].size();i++)
    60     {
    61         Edge temp=edge[now][i];
    62         if(temp.dest!=p) dfs2(temp.dest,now,temp.flag);
    63     }
    64 }
    65 
    66 void work()
    67 {
    68     dfs1(1,-1);
    69     dfs2(1,-1,233);
    70     cout<<ans<<endl;
    71     for(int i=1;i<=n;i++)
    72     {
    73         if(dp2[i]==ans) cout<<i<<" ";
    74     }
    75     cout<<endl;
    76 }
    77 
    78 int main()
    79 {
    80     read();
    81     work();
    82 }
  • 相关阅读:
    单例模式
    Curator Zookeeper分布式锁
    LruCache算法原理及实现
    lombok 简化java代码注解
    Oracle客户端工具出现“Cannot access NLS data files or invalid environment specified”错误的解决办法
    解决mysql Table ‘xxx’ is marked as crashed and should be repaired的问题。
    Redis 3.0 Cluster集群配置
    分布式锁的三种实现方式
    maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令
    How to Use Convolutional Neural Networks for Time Series Classification
  • 原文地址:https://www.cnblogs.com/Leohh/p/8256852.html
Copyright © 2011-2022 走看看