打卡信奥刷题(3360)用C++实现信奥题 P9593 「Daily OI Round 1」Block
P9593 「Daily OI Round 1」Block
题目描述
给定一棵树,节点有颜色,在树上距离为 222 的点连边(仍保留原来的边),求新图中颜色相同且连通的非空点集数量。由于答案可能非常大,您只需输出答案对 109+710^9+7109+7 取模的值。
点集连通的定义:对于图 G(V,E)G(V,E)G(V,E),VVV 的一个子集 V′V'V′ 是连通点集,当且仅当 G(V′,E′)G(V',E')G(V′,E′) 是一个连通图,其中边集 E′={(u,v)∣(u,v)∈E∧u∈V′∧v∈V′}E'=\{(u,v)|(u,v)\in E\land u \in V'\land v\in V'\}E′={(u,v)∣(u,v)∈E∧u∈V′∧v∈V′}。
输入格式
第一行一个正整数 nnn,表示节点个数。
接下来一行 nnn 个正整数,第 iii 个正整数 cic_ici 表示第 iii 个节点的颜色。
接下来 n−1n-1n−1 行每行两个正整数 u,vu,vu,v 表示原树有一条 uuu 到 vvv 的边。
输出格式
一行一个整数,表示答案对 109+710^9+7109+7 取模的值。
输入输出样例 #1
输入 #1
4
1 2 1 1
1 2
2 3
2 4
输出 #1
8
输入输出样例 #2
输入 #2
6
1 2 2 2 1 2
5 3
2 1
4 5
6 3
3 1
输出 #2
14
输入输出样例 #3
输入 #3
16
1 1 2 1 1 2 2 2 1 1 2 1 1 1 2 1
12 8
14 9
10 8
1 16
7 12
6 1
14 8
3 1
12 5
1 13
12 2
1 12
15 8
11 5
4 12
输出 #3
442
输入输出样例 #4
输入 #4
16
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
4 14
4 15
12 13
2 5
7 15
10 2
15 8
15 13
9 11
13 11
3 15
8 16
6 13
1 4
10 4
输出 #4
27454
输入输出样例 #5
输入 #5
9
3 3 2 3 2 4 2 3 3
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
输出 #5
16
说明/提示
样例 1 中,原树如下图所示:

树上距离为 222 的点连边后,新图如下图所示:

则 888 个颜色相同且连通的非空点集分别是:{1},{2},{3},{4},{1,3},{1,4},{3,4},{1,3,4}\{1\},\{2\},\{3\},\{4\},\{1,3\},\{1,4\},\{3,4\},\{1,3,4\}{1},{2},{3},{4},{1,3},{1,4},{3,4},{1,3,4}。
本题开启捆绑测试。
| Subtask\text{Subtask}Subtask | 分值 | n≤n \len≤ | 特殊性质 | 子任务依赖 |
|---|---|---|---|---|
| 000 | 555 | 10510^5105 | A | 无 |
| 111 | 555 | 161616 | 无 | 无 |
| 222 | 555 | 10510^5105 | B | 无 |
| 333 | 151515 | 10510^5105 | C | 无 |
| 444 | 202020 | 10510^5105 | D | 无 |
| 555 | 505050 | 10510^5105 | 无 | 0∼40\sim40∼4 |
- 特殊性质 A:所有节点的颜色不相同。
- 特殊性质 B:给出的树是菊花,具体地,第 iii 条边连接节点 111 和节点 i+1i+1i+1。
- 特殊性质 C:给出的树是链,具体地,第 iii 条边连接节点 iii 和节点 i+1i+1i+1。
- 特殊性质 D:所有节点的颜色相同。
对于全部数据,满足 2≤n≤1052\leq n\leq 10^52≤n≤105,1≤ci≤n1\leq c_i\leq n1≤ci≤n。
C++实现
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,P=1e9+7;
int n,c[N],dp[N],f[N],g[N],ans;
vector<int> G[N];
void dfs(int u,int fa){
for(int v:G[u])
if(v!=fa)dfs(v,u);
dp[u]=1;
for(int v:G[u])
if(v!=fa)
g[c[v]]=1ll*g[c[v]]*(dp[v]+1)%P;
f[u]=g[c[fa]];
for(int v:G[u])
if(v!=fa)
dp[u]=1ll*dp[u]*(f[v]+dp[v]*(c[v]==c[u]))%P;
for(int v:G[u])if(v!=fa)
ans=(ans+g[c[v]]-1)%P,g[c[v]]=1;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",c+i),g[i]=1;
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1,0);
printf("%d\n",(ans+dp[1])%P);
return 0;
}
.
后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)