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)EuVvV}

输入格式

第一行一个正整数 nnn,表示节点个数。

接下来一行 nnn 个正整数,第 iii 个正整数 cic_ici 表示第 iii 个节点的颜色。

接下来 n−1n-1n1 行每行两个正整数 u,vu,vu,v 表示原树有一条 uuuvvv 的边。

输出格式

一行一个整数,表示答案对 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\sim404
  • 特殊性质 A:所有节点的颜色不相同。
  • 特殊性质 B:给出的树是菊花,具体地,第 iii 条边连接节点 111 和节点 i+1i+1i+1
  • 特殊性质 C:给出的树是链,具体地,第 iii 条边连接节点 iii 和节点 i+1i+1i+1
  • 特殊性质 D:所有节点的颜色相同。

对于全部数据,满足 2≤n≤1052\leq n\leq 10^52n1051≤ci≤n1\leq c_i\leq n1cin

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考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐