考虑将每种颜色构成的极小连通块缩点,然后直接跑树形dp即可,即f[i][0/1]表示子树内是否有颜色向上延伸时删边的方案数。dp时需要去除某点的贡献,最好用前后缀积的做法而不是求逆。

  至于如何缩点,假装要给每种颜色建虚树,按dfs序排一下序找到所有虚树上的边,标记所有虚树上的点(包括不在虚树中但在虚树上两点的路径中)即可。然后重建树。注意标记过程中判一下无解。

  (这个div3F代码长度怎么跟我div1F差不多了啊?

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define P 998244353
#define N 300010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,a[N],p[N<<1],dfn[N],fa[N][20],deep[N],f[N<<1],F[N<<1][2],pre[N<<1],suf[N<<1],t,T,cnt,stk[N],top;
vector<int> pos[N];
struct data{int to,nxt;
}edge[N<<1],tree[N<<2];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void new_addedge(int x,int y){T++;tree[T].to=y,tree[T].nxt=p[x],p[x]=T;}
void dfs(int k)
{
dfn[k]=++cnt;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=fa[k][0])
{
fa[edge[i].to][0]=k;
deep[edge[i].to]=deep[k]+1;
dfs(edge[i].to);
}
}
bool cmp(const int&a,const int&b)
{
return dfn[a]<dfn[b];
}
int lca(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
for (int j=19;~j;j--) if (deep[fa[x][j]]>=deep[y]) x=fa[x][j];
if (x==y) return x;
for (int j=19;~j;j--) if (fa[x][j]!=fa[y][j]) x=fa[x][j],y=fa[y][j];
return fa[x][0];
}
bool paint(int x,int y,int color)
{
while (x!=y)
{
if (f[x]>n&&f[x]!=color) return 1;
f[x]=color;x=fa[x][0];
}
return 0;
}
void dp(int k,int from)
{
for (int i=p[k];i;i=tree[i].nxt)
if (tree[i].to!=from) dp(tree[i].to,k);
if (k>n)
{
F[k][0]=0;F[k][1]=1;
for (int i=p[k];i;i=tree[i].nxt)
if (tree[i].to!=from) F[k][1]=1ll*F[k][1]*(F[tree[i].to][0]+F[tree[i].to][1])%P;
}
else
{
F[k][0]=1;int cnt=0;
for (int i=p[k];i;i=tree[i].nxt)
if (tree[i].to!=from)
{
F[k][0]=1ll*F[k][0]*(F[tree[i].to][0]+F[tree[i].to][1])%P;
pre[++cnt]=F[tree[i].to][0]+F[tree[i].to][1];
}
for (int i=1;i<=cnt;i++) suf[i]=pre[i];
pre[0]=1;for (int i=1;i<=cnt;i++) pre[i]=1ll*pre[i-1]*pre[i]%P;
suf[cnt+1]=1;for (int i=cnt;i>=1;i--) suf[i]=1ll*suf[i]*suf[i+1]%P;
int t=0;
for (int i=p[k];i;i=tree[i].nxt)
if (tree[i].to!=from)
{
t++;
F[k][1]=(F[k][1]+1ll*pre[t-1]*suf[t+1]%P*F[tree[i].to][1])%P;
}
}
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("f.in","r",stdin);
freopen("f.out","w",stdout);
#endif
n=read(),m=read();
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<n;i++)
{
int x=read(),y=read();
addedge(x,y),addedge(y,x);
}
fa[1][0]=1;dfs(1);
for (int j=1;j<20;j++)
for (int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
for (int i=1;i<=n;i++)
if (a[i]) f[i]=n+a[i],pos[a[i]].push_back(i);else f[i]=i;
for (int i=1;i<=m;i++)
if (pos[i].size()>1)
{
sort(pos[i].begin(),pos[i].end(),cmp);
int root=(*pos[i].begin());
for (int j=0;j<pos[i].size()-1;j++)
if (deep[lca(pos[i][j],pos[i][j+1])]<deep[root]) root=lca(pos[i][j],pos[i][j+1]);
if (f[root]>n&&f[root]!=n+i) {cout<<0;return 0;}
top=0;stk[++top]=root;f[root]=n+i;
for (int j=((*pos[i].begin())==root);j<pos[i].size();j++)
{
int l=lca(stk[top],pos[i][j]);
if (l!=stk[top])
{
while (top>1&&deep[l]<=deep[stk[top-1]])
{
if (paint(stk[top],stk[top-1],n+i)) {cout<<0;return 0;}
top--;
}
if (paint(stk[top],l,n+i)) {cout<<0;return 0;}
stk[top]=l;
}
stk[++top]=pos[i][j];
}
while (top>1)
{
if (paint(stk[top],stk[top-1],n+i)) {cout<<0;return 0;}
top--;
}
}
//for (int i=1;i<=n;i++) cout<<f[i]<<' ';cout<<endl;
memset(p,0,sizeof(p));
for (int i=1;i<=t;i+=2)
if (f[edge[i].to]!=f[edge[i+1].to])
new_addedge(f[edge[i].to],f[edge[i+1].to]),
new_addedge(f[edge[i+1].to],f[edge[i].to]);
dp(n+1,n+1);
cout<<F[n+1][1];
return 0;
//NOTICE LONG LONG!!!!!
}

  

Codeforces Round #540 Div. 3 F2的更多相关文章

  1. Codeforces Round #540 (Div. 3) 部分题解

    Codeforces Round #540 (Div. 3) 题目链接:https://codeforces.com/contest/1118 题目太多啦,解释题意都花很多时间...还有事情要做,就选 ...

  2. Codeforces Round #540 (Div. 3) A,B,C,D2,E,F1

    A. Water Buying 链接:http://codeforces.com/contest/1118/problem/A 实现代码: #include<bits/stdc++.h> ...

  3. Codeforces Round #540 (Div. 3)--1118C - Palindromic Matrix

    https://codeforces.com/contest/1118/problem/C 在查找元素的时候,必须按4,2,1的顺序进行.因为,如果先找1,可能就把原来的4拆散了,然后再找4,就找不到 ...

  4. Codeforces Round #540 (Div. 3)--1118F1 - Tree Cutting (Easy Version)

    https://codeforces.com/contest/1118/problem/F1 #include<bits/stdc++.h> using namespace std; in ...

  5. Codeforces Round #540 (Div. 3)--1118D2 - Coffee and Coursework (Hard Version)

    https://codeforces.com/contest/1118/problem/D2 和easy version的主要区别是,数据增加了. easy version采用的是线性查找,效率低 在 ...

  6. Codeforces Round #540 (Div. 3)--1118D1 - Coffee and Coursework (Easy version)

    https://codeforces.com/contest/1118/problem/D1 能做完的天数最大不超过n,因为假如每天一杯咖啡,每杯咖啡容量大于1 首先对容量进行从大到小的排序, sor ...

  7. Codeforces Round #540 (Div. 3)题解

    题目链接: https://codeforces.com/contest/1118 A题: 题意: q次查询,给你一个n,要你用1和2来凑出n,1的花费为a,2的花费为b,求花费的最小值. 思路: 我 ...

  8. Codeforces Round #540 (Div. 3) F1. Tree Cutting (Easy Version) 【DFS】

    任意门:http://codeforces.com/contest/1118/problem/F1 F1. Tree Cutting (Easy Version) time limit per tes ...

  9. Codeforces Round #540 (Div. 3) D1. Coffee and Coursework (Easy version) 【贪心】

    任意门:http://codeforces.com/contest/1118/problem/D1 D1. Coffee and Coursework (Easy version) time limi ...

随机推荐

  1. WPF仿网易云音乐系列(二、歌单创建窗口+登录设置模块)

    老衲牺牲午休时间写博客,都快把自己感动了,-_-!! 之前上一篇随笔,我看了下评论,有部分人说WPF已经凉凉了,这个我觉得,这只是一个达到自己目的的工具而已,只要自己能用这个工具,得心应手的做出自己想 ...

  2. TCP/IP 协议 OSI七层协议

    ------------------你来自何处并不重要,重要的是你要去往何方,人生最重要的不是所站的位置,而是所去的方向.人只要不失去方向,就永远不会失去自己! day 27 # # -------- ...

  3. form,ajax注册,logging日志使用

    一.form表单类型提交注册信息 二.ajax版本提交注册信息 <!DOCTYPE html> <html lang="en"> <head> ...

  4. 腾讯内推一面C++

    北邮论坛找个腾讯的内推,没想到那么快就安排面试了.第一次面腾讯,写点东西记录一下吧. 面的是位置服务部门. 去了之后HR先给了两张纸,有三道编程题.第一道是求 二进制中1的个数(考察位运算)(剑指of ...

  5. Technical Development Guide---for Google

    Technical Development Guide This guide provides tips and resources to help you develop your technica ...

  6. 网络编程-TCP/IP

    TCP/IP五层模型讲解(2分) 我们将应用层,表示层,会话层并作应用层,从tcp/ip五层协议的角度来阐述每层的由来与功能,搞清楚了每层的主要协议 就理解了整个互联网通信的原理. 首先,用户感知到的 ...

  7. C. Polycarp Restores Permutation

    链接 [https://codeforces.com/contest/1141/problem/C] 题意 qi=pi+1−pi.给你qi让你恢复pi 每个pi都不一样 分析 就是数学吧 a1 +(a ...

  8. (第十三周)评论Final发布II

    按课上展示的顺序对每组进行点评:(性能.功能.UI.部署) 1.  Nice! 项目:约跑软件 软件操作的响应很快,俩人进行聊天时可以实现消息的及时传递.功能主要有:注册账号.登录.创建/删除跑步计划 ...

  9. CNZZ友盟访问明细的采集办法

    www.cnzz.com是中文网站统计分析平台,很多站长需要获取网站提供的访问明细,以做分析. 直接采集这个网站的数据相当麻烦,通过浏览器或者fiddlercore就简单多了. 2.0新版,通过浏览器 ...

  10. 合并dll文件

    在使用VS进行.Net编程时,出现了一个奇怪的现象. 在一个类库项目中导入了dll库A后,再导入A的两个依赖项(dll库)B和C,执行“生成”操作时,出现错误信息,提示B和C的库版本与A所需的不一致. ...