zoukankan      html  css  js  c++  java
  • CodeForces 543d Road Improvement

    Road Improvement

    Time Limit: 2000ms
    Memory Limit: 262144KB
    This problem will be judged on CodeForces. Original ID: 543D
    64-bit integer IO format: %I64d      Java class name: (Any)

    The country has n cities and n - 1 bidirectional roads, it is possible to get from every city to any other one if you move only along the roads. The cities are numbered with integers from1 to n inclusive.

    All the roads are initially bad, but the government wants to improve the state of some roads. We will assume that the citizens are happy about road improvement if the path from the capital located in city x to any other city contains at most one bad road.

    Your task is — for every possible x determine the number of ways of improving the quality of some roads in order to meet the citizens' condition. As those values can be rather large, you need to print each value modulo 1 000 000 007 (109 + 7).

     

    Input

    The first line of the input contains a single integer n (2 ≤ n ≤ 2·105) — the number of cities in the country. Next line contains n - 1 positive integers p2, p3, p4, ..., pn (1 ≤ pi ≤ i - 1) — the description of the roads in the country. Number pi means that the country has a road connecting city pi and city i.

     

    Output

    Print n integers a1, a2, ..., an, where ai is the sought number of ways to improve the quality of the roads modulo 1 000 000 007 (109 + 7), if the capital of the country is at city number i.

     

    Sample Input

    Input
    3
    1 1
    Output
    4 3 3
    Input
    5
    1 2 3 4
    Output
    5 8 9 8 5

    Source

     
    解题:树形dp
     
    dp[u]表示以u为根的方案数,dp[u] = (dp[v]+1)*(dp[v2]+1)...
     
    为什么加1?因为如果u到v的路修的话就是dp[v],如果不修,那么只有1种方案,子树都要修
     
    那么我们如何计算任意点位根的数量呢
     
    假设当前早在v 其父亲为u dp2[u]表示以u为根倒回去的方案数,那么以为根的方案数是多少?
     
    很显然我们要计算出v的兄弟的方案数,(dp[v]+1)*(dp[v2]+1)...
     
    乘上u倒回去的方案数 
     
    就是去掉v这棵树 以u为根的方案数,
     现在加上v
    u到v的边可以修,那么就是前面的方案数,如果不修,那只有一种方案
     
    也就是说前面的积+1后
    乘以以v为根的方案数dp[v]。。就是以v为首都的可行方案数
     
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int maxn = 200010;
     5 vector<int>g[maxn];
     6 LL dp[maxn],dp2[maxn];
     7 const LL mod = 1000000007;
     8 void dfs(int u,int fa){
     9     dp[u] = 1;
    10     for(int i = g[u].size()-1; i >= 0; --i){
    11         if(g[u][i] == fa) continue;
    12         dfs(g[u][i],u);
    13         dp[u] = dp[u]*(dp[g[u][i]]+1)%mod;
    14     }
    15 }
    16 LL L[maxn],R[maxn];
    17 void dfs2(int u,int fa){
    18     int m = g[u].size();
    19     L[0] = 1;
    20     R[m - 1] = dp2[u];
    21     for(int i = 1; i < m; ++i)
    22         L[i] = L[i-1]*(dp[g[u][i-1]]+1)%mod;
    23     for(int i = m-2; i >= 0; --i)
    24         R[i] = R[i+1]*(dp[g[u][i+1]]+1)%mod;
    25     for(int i = 0; i < m; ++i){
    26         if(g[u][i] == fa) continue;
    27         dp2[g[u][i]] = (L[i]*R[i] + 1)%mod;
    28     }
    29     for(int i = 0; i < m; ++i){
    30         if(g[u][i] == fa) continue;
    31         dfs2(g[u][i],u);
    32     }
    33 }
    34 int main(){
    35     int n,o;
    36     scanf("%d",&n);
    37     for(int i = 2; i <= n; ++i){
    38         scanf("%d",&o);
    39         g[o].push_back(i);
    40     }
    41     dp2[1] = 1;
    42     dfs(1,0);
    43     dfs2(1,0);
    44     for(int i = 1; i <= n; ++i)
    45         cout<<dp2[i]*dp[i]%mod<<(i == n?"
    ":" ");
    46     return 0;
    47 }
    View Code
  • 相关阅读:
    linux开启oracle服务
    一个tomcat多域名绑定多项目
    linux安装jdk1.7.0
    windows 查看端口进程和杀死进程
    windows2008 扩大远程连接数
    windows下用bak文件备份数据库
    linux常用命令
    mysql 开启远程连接访问
    windows 下tomcat安装
    IBM公司面试题
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4663677.html
Copyright © 2011-2022 走看看