解题: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
原文地址:https://www.cnblogs.com/ydnhaha/p/10430135.html