zoukankan      html  css  js  c++  java
  • 解题:CF1118F2 Tree Cutting (Hard Version)

    题面

    好题不问Div(这是Div3最后一题,不得不说Mike真是强=。=)

    首先同一个颜色的点的LCA要和它们在一个划分出的块里,那么我们先按颜色把所有点到它们的LCA的路径涂色,如果这个过程中出现了重合的颜色则说明无解。

    之后问题转化为一个树形DP问题,设$dp[i][0/1]$表示以$i$为根的子树中i是否划入一个有颜色的块的方案数。然后讨论转移:

    1.如果i自身没有颜色

    ①如果i不划入有颜色的块,那么直接继承子树信息,乘法原理统计,$dp[i][0]=prod_{v∈son_i}(dp[v][0]+dp[v][1])$

    ②如果i划入有颜色的块,那么对于每一个子树都单独统计一遍划入其中的方案数,$dp[i][1]=sum_{v∈son_i}dp[v][1]prod_{w∈son_i&&w!=v}(dp[w][0]+dp[w][1])$,维护每个节点子节点的前缀后缀乘积来转移

    2.如果i自身有颜色

    ①如果i不划入有颜色的块,那么......不划入有颜色的块=。=???$dp[i][0]=0$

    ②如果i划入有颜色的块,同理于1.①

    (因为一个睿智错误多调了一个小时

      1 #include<cstdio>
      2 #include<vector>
      3 #include<cstring>
      4 #include<algorithm>
      5 #define vint vector<int>
      6 #define vit vector<int>::iterator
      7 using namespace std;
      8 const int N=300005,mod=998244353;
      9 int p[N],noww[2*N],goal[2*N],siz[N];
     10 int anc[N],dep[N],imp[N],top[N],col[N],dp[N][2]; 
     11 int n,k,cnt,t1,t2; vint ve[N];
     12 void Link(int f,int t)
     13 {
     14     noww[++cnt]=p[f];
     15     goal[cnt]=t,p[f]=cnt;
     16     noww[++cnt]=p[t];
     17     goal[cnt]=f,p[t]=cnt;
     18 }
     19 void Add(int &x,int y)
     20 {
     21     x+=y;
     22     if(x>=mod) x-=mod;
     23 }
     24 void Mul(int &x,int y)
     25 {
     26     x=1ll*x*y%mod;
     27 }
     28 void DFS(int nde,int fth,int dth)
     29 {
     30     int tmp=0;
     31     siz[nde]=1,anc[nde]=fth,dep[nde]=dth;
     32     for(int i=p[nde];i;i=noww[i])
     33         if(goal[i]!=fth)
     34         {
     35             DFS(goal[i],nde,dth+1);
     36             siz[nde]+=siz[goal[i]];
     37             if(siz[goal[i]]>tmp)
     38                 tmp=siz[goal[i]],imp[nde]=goal[i];
     39         }
     40 }
     41 void Decompose(int nde,int tpp)
     42 {
     43     top[nde]=tpp;
     44     if(imp[nde])
     45     {
     46         Decompose(imp[nde],tpp);
     47         for(int i=p[nde];i;i=noww[i])
     48             if(goal[i]!=anc[nde]&&goal[i]!=imp[nde])
     49                 Decompose(goal[i],goal[i]);
     50     }
     51 }
     52 int LCA(int x,int y)
     53 {
     54     while(top[x]!=top[y])
     55     {
     56         if(dep[top[x]]<dep[top[y]])
     57             swap(x,y); x=anc[top[x]];
     58     }
     59     return dep[x]<dep[y]?x:y;
     60 }
     61 void Climb(int nde,int lca,int cor)
     62 {
     63     while(nde!=lca)
     64     {
     65         nde=anc[nde];
     66         if(col[nde])
     67         {
     68             if(col[nde]==cor) return;
     69             else printf("0"),exit(0);
     70         }
     71         col[nde]=cor;
     72     }
     73 }
     74 void Getans(int nde,int fth)
     75 {
     76     vint v1,v2; 
     77     dp[nde][(bool)col[nde]]=1;
     78     for(int i=p[nde];i;i=noww[i])
     79         if(goal[i]!=fth)
     80         {
     81             int g=goal[i]; Getans(g,nde);
     82             int s=(dp[g][0]+dp[g][1])%mod;
     83             v1.push_back(s),v2.push_back(s);
     84             col[nde]?Mul(dp[nde][1],s):Mul(dp[nde][0],s);
     85         }
     86     if(!col[nde]&&v1.size())
     87     {
     88         int sz=v1.size(),pt=0;
     89         for(int i=1;i<sz;i++) Mul(v1[i],v1[i-1]);
     90         for(int i=sz-2;i>=0;i--) Mul(v2[i],v2[i+1]);
     91         for(int i=p[nde];i;i=noww[i])
     92             if(goal[i]!=fth)
     93             {
     94                 int pre=pt?v1[pt-1]:1,suf=(pt==sz-1)?1:v2[pt+1];
     95                 int tmp=dp[goal[i]][1]; 
     96                 Mul(tmp,pre),Mul(tmp,suf),Add(dp[nde][1],tmp),pt++;
     97             }
     98     }
     99 }
    100 int main ()
    101 {
    102     scanf("%d%d",&n,&k);
    103     for(int i=1;i<=n;i++)
    104     {
    105         scanf("%d",&col[i]);
    106         if(col[i]) ve[col[i]].push_back(i);
    107     }
    108     for(int i=1;i<n;i++)
    109         scanf("%d%d",&t1,&t2),Link(t1,t2);
    110     DFS(1,0,1),Decompose(1,1);
    111     for(int i=1;i<=k;i++)
    112     {
    113         vint v=ve[i]; int lca=*v.begin();
    114         if(v.size()>1) 
    115         {
    116             vit it=++v.begin();
    117             while(it!=v.end())
    118                 lca=LCA(lca,*it++);
    119         }
    120         vit it=v.begin();
    121         while(it!=v.end())
    122             Climb(*it++,lca,i);
    123     }
    124     Getans(1,0);
    125 //    for(int i=1;i<=n;i++) 
    126 //        printf("%d %d %d
    ",mar[i],dp[i][0],dp[i][1]);    
    127     printf("%d",dp[1][1]);
    128     return 0;
    129 }
    View Code
  • 相关阅读:
    《计算机网络》总结
    【操作系统】死锁
    【操作系统】进程同步
    【操作系统】处理器调度
    【操作系统】总结二(进程与线程)
    【操作系统】总结一
    前缀、中缀、后缀表达式
    QMap
    Qt 常用的功能
    Qt 文件处理
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10430135.html
Copyright © 2011-2022 走看看