zoukankan      html  css  js  c++  java
  • Codeforces Round #263 (Div. 2) D. Appleman and Tree(树形DP)

    题目链接

    D. Appleman and Tree

    time limit per test :2 seconds
    memory limit per test: 256 megabytes
    input :standard input
    output:standard output

    Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other vertices are colored white.

    Consider a set consisting of k (0 ≤ k < n) edges of Appleman's tree. If Appleman deletes these edges from the tree, then it will split into(k + 1) parts. Note, that each part will be a tree with colored vertices.

    Now Appleman wonders, what is the number of sets splitting the tree in such a way that each resulting part will have exactly one black vertex? Find this number modulo 1000000007 (109 + 7).

    Input

    The first line contains an integer n (2  ≤ n ≤ 105) — the number of tree vertices.

    The second line contains the description of the tree: n - 1 integers p0, p1, ..., pn - 2 (0 ≤ pi ≤ i). Where pi means that there is an edge connecting vertex (i + 1) of the tree and vertex pi. Consider tree vertices are numbered from 0 to n - 1.

    The third line contains the description of the colors of the vertices: n integers x0, x1, ..., xn - 1 (xi is either 0 or 1). If xi is equal to 1, vertex i is colored black. Otherwise, vertex i is colored white.

    Output

    Output a single integer — the number of ways to split the tree modulo 1000000007 (109 + 7).

    Sample test(s)
    input
    3
    0 0
    0 1 1
    output
    2
    input
    6
    0 1 1 0 4
    1 1 0 0 1 0
    output
    1
    input
    10
    0 1 2 1 4 4 4 0 8
    0 0 0 1 0 1 1 0 0 1
    output
    27

    题意:对每个节点染色,白或者黑,问你断开某些边,使得每个联通块都恰好只有一个节点时黑色,问有多少种断边方式。

    思路 :树形DP,  dp[i][0]代表到 i 这个点它所在的子树只有一个黑点的情况,dp[i][0] 包含i节点的这部分没有黑点的情况数。

    对于每个节点 i,计算到它的一个子树(根节点u) (设连接的边为edge)的时候,dp[i][0] 为dp[i][0] * dp[u][1] + dp[i][0] * dp[u][0], 已处理完的一定要取dp[i][0], 如果取edge 则子树取dp[u][0],如果不取edge, 则子树取dp[u][1].

    dp[i][1] 为 dp[i][1] *(dp[u][0] + dp[u][1]) + dp[i][0] *dp[u][1] , 如果处理完的取dp[i][1],edge取的话为dp[u][0], 不取的话为dp[u][1]; 如果处理完的取dp[i][0], edge一定要取且要乘以dp[u][1]  (ps: dp[u][0] 不能要,如果要的话 u点的部分会出现不含黑点的情况)

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <iostream>
     4 #define mod 1000000007
     5 
     6 using namespace std ;
     7 
     8 struct node
     9 {
    10     int u ;
    11     int v ;
    12     int next ;
    13 }p[100010];
    14 int cnt,head[100010],color[100010] ;
    15 long long dp[100010][2] ;
    16 
    17 void addedge(int u,int v)
    18 {
    19     p[cnt].u = u ;
    20     p[cnt].v = v ;
    21     p[cnt].next = head[u] ;
    22     head[u] = cnt ++ ;
    23 }
    24 void DFS(int u)
    25 {
    26     dp[u][color[u]] = 1 ;
    27     for(int i = head[u] ; i+1 ; i = p[i].next)
    28     {
    29         int v = p[i].v ;
    30         DFS(v) ;
    31         dp[u][1] = ((dp[u][1] * dp[v][0]) % mod + (dp[u][1] * dp[v][1]) % mod + (dp[u][0] * dp[v][1]) % mod) % mod ;
    32         dp[u][0] = ((dp[u][0] * dp[v][0]) % mod + (dp[u][0] * dp[v][1]) % mod) % mod ;
    33     }
    34 }
    35 int main()
    36 {
    37     int n ,a;
    38     while(~scanf("%d",&n))
    39     {
    40         cnt = 0 ;
    41         memset(head,-1,sizeof(head)) ;
    42         memset(dp,0,sizeof(dp)) ;
    43         for(int i = 1 ; i < n ; i++)
    44         {
    45             scanf("%d",&a) ;
    46             addedge(a,i) ;
    47         }
    48         for(int i = 0 ; i < n ; i++)
    49             scanf("%d",&color[i]) ;
    50         DFS(0) ;
    51         printf("%I64d
    ",dp[0][1]) ;
    52     }
    53     return 0 ;
    54 }
    View Code
  • 相关阅读:
    面试题:增强一个对象的方法的三种方式
    Spring笔记01_下载_概述_监听器
    mybatis笔记02
    mybatis笔记01
    muduo学习笔记(二)Reactor关键结构
    Muduo学习笔记(一) 什么都不做的EventLoop
    一个linux下简单的纯C++实现Http请求类(GET,POST,上传,下载)
    一个轻巧高效的多线程c++stream风格异步日志(二)
    一个轻巧高效的多线程c++stream风格异步日志(一)
    C++智能指针,指针容器原理及简单实现(auto_ptr,scoped_ptr,ptr_vector).
  • 原文地址:https://www.cnblogs.com/luyingfeng/p/3939754.html
Copyright © 2011-2022 走看看