zoukankan      html  css  js  c++  java
  • CodeForces 461B Appleman and T

    题目链接:http://codeforces.com/contest/461/problem/B

    题目大意:

      给定一课树,树上的节点有黑的也有白的,有这样一种分割树的方案,分割后每个子图只含有一个黑色节点,问这样的分割方案一共有多少种?

    分析:

    先定义3个函数(为了之后说起来方便):

      设A(x) = 在以顶点x为根的子树中,所有满足使x所在子图不含黑色顶点,其余子图只含有1个黑色顶点的分割方案种数 。
      设B(x) = 在以顶点x为根的子树中,所有满足每个子图只含有1个黑色顶点的分割方案种数 。
      设C(x) = 在以顶点x为根的子树中,所有满足使x所在子图只含有1个黑色顶点,其余子图只含有1个黑色顶点的分割方案种数 。
      显然B(x) = C(x)

      首先我们关注某一课子树的根节点,不妨设为rt,有2种情况:
      不妨设rt有a个黑色的孩子节点,b个白色的孩子节点,rt的第i个黑色节点表示为rtBi,白色节点表示为rtWi,rt的第i个孩子节点表示为soni

    1 : color[rt] == WHITE
      初始条件下B(rt) = 0
      在这种情况下,rt与每个孩子节点都有相连与不相连2种策略,对于soni,不相连的贡献自然是B(soni),而相连的贡献就不是独立的了,很可能有跨越根节点到其他子树的方案,也就是说,对于每一棵子树,都要和其他每一棵子树有深入交流。
      我们可以考虑增而治之,设rtSonsi为以rt为根节点,只拥有前i个孩子节点的树,A(rt),B(rt),C(rt)为相应数值,初始状态为A(rt) = 1,B(rt) = 0,C(rt) = 0,我们只要考虑soni+1加入时,A(rt),B(rt),C(rt)会如何变化,当子树全部加入时,就算完了。这里有2种情况:
      (1)与soni+1相连:B(rt)  = C(rt) = A(rt) * C(soni+1) + C(rt) * A(soni+1)
                                        A(rt) = A(rt) * A(soni+1)
      (2)与soni+1不相连:B(rt)  = C(rt) = C(rt) * C(soni+1)
                                            A(rt) = A(rt) * C(soni+1)
      于是总变化为:B(rt)  = C(rt) = A(rt) * C(soni+1) + C(rt) * [A(soni+1) + C(soni+1)]
                               A(rt) = A(rt) * [A(soni+1) + C(soni+1)]
     
     
    2:color[rt] == BLACK
      初始条件下B(rt) = 1,自己自身算一个
      在这种情况下,rt一定不能与黑色的孩子节点相连,而对于白色的孩子节点,有相连与不相连两种选择。
      同样增而治之,设rtSonsi为以rt为根节点,只拥有前i个孩子节点的树,A(rt),B(rt),C(rt)为相应数值,初始状态为A(rt) = 0,B(rt) = 1,C(rt) = 1并且A(rt)恒等于0,我们只要考虑soni+1加入时,A(rt),B(rt),C(rt)会如何变化,当子树全部加入时,就算完了。这里有3种情况:
      (1)soni+1为白色节点&&与soni+1相连:B(rt)  = C(rt) = C(rt) * A(soni+1)
      (2)soni+1为白色节点&&与soni+1不相连:B(rt)  = C(rt) = C(rt) * C(soni+1)
      (3)soni+1为黑色节点(和2是同一种情况):B(rt)  = C(rt) = C(rt) * C(soni+1)
      于是总变化为:B(rt)  = C(rt) = C(rt) * [A(soni+1) + C(soni+1)]

     
    一个优化:对于color[rt] == BLACK的情况,如果我们把rt看成是白色的,然后照此计算出A(rt),B(rt),C(rt),那么以rt为根节点的子树的真实方案数,不就是A(rt)吗?这样的话就没有必要分情况了,在最后加个判断即可。

     

    代码如下:

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3  
      4 #define rep(i,n) for (int i = 0; i < (n); ++i)
      5 #define For(i,s,t) for (int i = (s); i <= (t); ++i)
      6 #define rFor(i,t,s) for (int i = (t); i >= (s); --i)
      7 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
      8 #define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i)
      9  
     10 #define pr(x) cout << #x << " = " << x << "  "
     11 #define prln(x) cout << #x << " = " << x << endl
     12  
     13 #define LOWBIT(x) ((x)&(-x))
     14  
     15 #define ALL(x) x.begin(),x.end()
     16 #define INS(x) inserter(x,x.begin())
     17  
     18 #define ms0(a) memset(a,0,sizeof(a))
     19 #define msI(a) memset(a,inf,sizeof(a))
     20 #define msM(a) memset(a,-1,sizeof(a))
     21  
     22 #define pii pair<int,int> 
     23 #define piii pair<pair<int,int>,int> 
     24 #define mp make_pair
     25 #define pb push_back
     26 #define fi first
     27 #define se second
     28  
     29 inline int gc(){
     30     static const int BUF = 1e7;
     31     static char buf[BUF], *bg = buf + BUF, *ed = bg;
     32      
     33     if(bg == ed) fread(bg = buf, 1, BUF, stdin);
     34     return *bg++;
     35 } 
     36  
     37 inline int ri(){
     38     int x = 0, f = 1, c = gc();
     39     for(; c<48||c>57; f = c=='-'?-1:f, c=gc());
     40     for(; c>47&&c<58; x = x*10 + c - 48, c=gc());
     41     return x*f;
     42 }
     43  
     44 typedef long long LL;
     45 typedef unsigned long long uLL;
     46 const int inf = 1e9 + 9;
     47 const LL mod = 1e9 + 7;
     48 const int maxN = 1e5 + 7;
     49  
     50 struct Node{
     51     vector< int > next;
     52 };
     53  
     54 int n, ans;
     55  
     56 /*
     57     设A(x) = 在以顶点x为根的子树中,所有满足使x所在子图不含黑色顶点,其余子图只含有1个黑色顶点的分割方案种数 
     58     设B(x) = 在以顶点x为根的子树中,所有满足每个子图只含有1个黑色顶点的分割方案种数 
     59     设C(x) = 在以顶点x为根的子树中,所有满足使x所在子图只含有1个黑色顶点,其余子图只含有1个黑色顶点的分割方案种数 
     60     则有: 
     61         dp[v][0] = A(v) + B(v)
     62         dp[v][1] = B(v)
     63         C(v) = B(v)
     64     The answer is dp[0][1].
     65 */
     66 LL dp[maxN][2];
     67 Node nodes[maxN];
     68 int color[maxN];
     69  
     70 void dfs(int x) {
     71     // 默认顶点x为白色 
     72     dp[x][0] = 1;
     73     dp[x][1] = 0;
     74      
     75     foreach(i, nodes[x].next) {
     76         dfs(*i);
     77         // dp[*i][0] 包含 A(*i) 和 C(*i),对于A(*i),令其与C(x)相连
     78         // 而对于C(*i),令其与C(x)分断 
     79         dp[x][1] = (dp[x][1] * dp[*i][0]) % mod;
     80         // dp[x][0] 包含 A(x),令其与C(*i)相连
     81           dp[x][1] = (dp[x][1] + dp[x][0] * dp[*i][1]) % mod;
     82           // 此时dp[x][0] = A(x) 
     83           // dp[x][0] * dp[*i][0] = A(x)*A(*i) + A(x)*C(*i)
     84           // 依次是连接新子树的A(*i)部分和断掉新子树的C(*i)部分,两这都可以保证dp[x][0]更新后还是A(x) 
     85           dp[x][0] = (dp[x][0] * dp[*i][0]) % mod;
     86     }
     87      
     88     if(color[x] == 1) dp[x][1] = dp[x][0]; // 当根节点为黑色时,A(x)实际上是C(x),而真正的A(x) = 0 
     89     else dp[x][0] = (dp[x][0] + dp[x][1]) % mod; // 此时 dp[x][0] = A(x) + C(x)
     90 }
     91  
     92 int main(){
     93     while(cin >> n) {
     94         rep(i, n) nodes[i].next.clear();
     95         For(i, 1, n-1) {
     96             int t;
     97             cin >> t;
     98             // 根据题目要求,并不需要加反向边 
     99             nodes[t].next.push_back(i);
    100         }
    101         rep(i, n) cin >> color[i];
    102          
    103         dfs(0);
    104          
    105         cout << dp[0][1] <<endl;
    106     }
    107     return 0;
    108 }
    View Code
  • 相关阅读:
    (OK)(OK) running two Android-x86 in VirtualBox, they connect to NS3(MANETs) via "ethernet bridge"
    (OK) running two Android-x86 in VirtualBox, they connect to "ethernet bridge"
    (OK) virtualbox — VBoxManage internalcommands — with UUID already exists
    (OK) netcat transfer file to android from fedora23
    Setting VirtualBox to use it's built-in VNC server (ver. >= 4.2 I think)
    (OK) Android 6.0 (Marshmallow) Install apk
    netcat——Useful netcat examples on Linux
    Android下pm 命令详解
    (OK) Ubuntu 15.10: KVM vs. Xen vs. VirtualBox Virtualization Performance
    Virtualization solutions on Linux systems
  • 原文地址:https://www.cnblogs.com/zaq19970105/p/10752471.html
Copyright © 2011-2022 走看看