ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

打卡信奥刷题(3505)用C++实现信奥题 P10842 【MX-J2-T3】Piggy and Trees

2026/8/13 10:46:56 拓冰建站 浏览量
打卡信奥刷题(3505)用C++实现信奥题 P10842 【MX-J2-T3】Piggy and Trees

P10842 【MX-J2-T3】Piggy and Trees

题目背景

原题链接:https://oier.team/problems/J2D。

题目描述

给你一棵n nn个结点的树。

定义f ( u , v , i ) f(u, v, i)f(u,v,i)为,在所有满足† dis ( u , x ) + dis ( v , x ) = dis ( u , v ) ^\dagger\text{dis}(u, x) + \text{dis}(v, x) = \text{dis}(u, v)dis(u,x)+dis(v,x)=dis(u,v)的点x xx中,dis ( x , i ) \text{dis}(x, i)dis(x,i)的最小值。

∑ u = 1 n ∑ v = u + 1 n ∑ i = 1 n f ( u , v , i ) \sum\limits_{u = 1}^n \sum\limits_{v = u + 1}^n \sum\limits_{i = 1}^n f(u, v, i)u=1nv=u+1ni=1nf(u,v,i)10 9 + 7 10^9 + 7109+7取模的值。

† dis ( u , v ) ^\dagger\text{dis}(u, v)dis(u,v)为树上u , v u, vu,v两点的路径长度。特别地,dis ( u , u ) = 0 \text{dis}(u, u) = 0dis(u,u)=0

输入格式

第一行包含一个整数n nn,表示树的结点数。

之后的n − 1 n - 1n1行中的第i ii行包含两个整数u i , v i u_i, v_iui,vi,表示树上的一条边。

输出格式

输出一行一个整数,表示答案。

输入输出样例 #1

输入 #1

4 1 2 1 3 1 4

输出 #1

9

输入输出样例 #2

输入 #2

6 1 2 2 3 3 4 4 5 5 6

输出 #2

70

输入输出样例 #3

输入 #3

10 1 2 1 3 1 4 2 5 3 6 2 7 4 8 8 9 9 10

输出 #3

536

说明/提示

【样例解释】

在样例1 11中,所有非0 00f ( u , v , i ) f(u, v, i)f(u,v,i)的值为:

  • f ( 1 , 2 , 3 ) = 1 f(1, 2, 3) = 1f(1,2,3)=1
  • f ( 1 , 2 , 4 ) = 1 f(1, 2, 4) = 1f(1,2,4)=1
  • f ( 1 , 3 , 2 ) = 1 f(1, 3, 2) = 1f(1,3,2)=1
  • f ( 1 , 3 , 4 ) = 1 f(1, 3, 4) = 1f(1,3,4)=1
  • f ( 1 , 4 , 2 ) = 1 f(1, 4, 2) = 1f(1,4,2)=1
  • f ( 1 , 4 , 3 ) = 1 f(1, 4, 3) = 1f(1,4,3)=1
  • f ( 2 , 3 , 4 ) = 1 f(2, 3, 4) = 1f(2,3,4)=1
  • f ( 2 , 4 , 3 ) = 1 f(2, 4, 3) = 1f(2,4,3)=1
  • f ( 3 , 4 , 2 ) = 1 f(3, 4, 2) = 1f(3,4,2)=1
【数据范围】

本题采用捆绑测试且开启子任务依赖。

子任务编号分值n ≤ n \len特殊性质子任务依赖
1 118 8850 5050
2 2215 1515400 4004001 11
3 3324 24243000 300030001 , 2 1, 21,2
4 4417 17172 ⋅ 10 5 2 \cdot 10^52105u i = i , v i = i + 1 u_i = i, v_i = i + 1ui=i,vi=i+1
5 5536 36362 ⋅ 10 5 2 \cdot 10^521051 , 2 , 3 , 4 1, 2, 3, 41,2,3,4

对于所有数据,满足2 ≤ n ≤ 2 ⋅ 10 5 2 \le n \le 2 \cdot 10^52n2105,输入的图是一棵树。

C++实现

#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintmod=1e9+7;vector<int>edge[200010];intsz[200010];intn,ans=0;voiddfs(intu,intfa){sz[u]=1;for(autov:edge[u]){if(v==fa)continue;dfs(v,u);sz[u]+=sz[v];}if(u==1)return;intsum=n-sz[u];// 朝“上”子树大小ans+=sum*(sum-1)/2*sz[u]+sz[u]*(sz[u]-1)/2*sum;ans%=mod;}signedmain(){cin>>n;for(inti=1;i<n;i++){intu,v;cin>>u>>v;edge[u].push_back(v);edge[v].push_back(u);}dfs(1,0);cout<<ans;return0;}

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容