AtCoder_221_f Diameter set 题解

思维模拟加数学因为是最远点,故必定为直径。 我们知道树的直径并不为一。但是考虑一下,如果一棵树的直径中有奇数个结点,其实对于它来说其“中心结点”是每一条直径都必须通过的。(证明靠脑子)由上面那个想法我们可以类比出偶数结点的情况,那么其“中心”将会变成一条边,也就是说这条边两边的点是必被直径通过的存在。所以,当结点为偶数时,只需要分别计算两侧结点所领导的子树中有多少个结点的深度是直径的一半即可。但是在结点数为奇数个时问题就会有转变,因为类似于“菊花图”这种的,其实它隐含了一个组合问题,是
摘要由CSDN通过智能技术生成

思维模拟加数学

因为是最远点,故必定为直径。
	
我们知道树的直径并不为一。但是考虑一下,如果一棵树的直径中有奇数个结点,其实对于它来说其“中心结点”是
每一条直径都必须通过的。(证明靠脑子)

由上面那个想法我们可以类比出偶数结点的情况,那么其“中心”将会变成一条边,也就是说这条边两边的点是必被
直径通过的存在。

所以,当结点为偶数时,只需要分别计算两侧结点所领导的子树中有多少个结点的深度是直径的一半即可。

但是在结点数为奇数个时问题就会有转变,因为类似于“菊花图”这种的,其实它隐含了一个组合问题,是:组间
可以同时出现,而组内不能同时出现,且至少要出现两个结点,问有多少种选择点的集合的方式。
	我们可以考虑的是由于“组内互斥”(不能同时出现)所以对于一个大小为 x 的组,它可以选择的结点有 x+1 种
	(因为可以不选)那么在满足“组内互斥”前提下总的选择方案为 (x1+1)*(x2+1)*(x3+1)*…*(xm+1) 其中 m 是
	组数。
	但是在上述选择下我们并没有考虑“至少出现两个结点”的条件,我们计算的是出现零个、一个、两个……一直到出
	现 m 个的情况,那么我们只需要删除出现零个和一个的情况就可以了,其分别为 1 和 x1+x2+…+xm 种情况。
#include <bits/stdc++.h>
using namespace std;

#define ll long long 
#define _for(i, a, b) for(int i = (a); i <= (b); i ++)
inline void read(int &x, int &y) {
    scanf("%d%d", &x, &y); }
int mod = 998244353;

int n;

int head[200009], nex[400009], to[400009], tot;  /// 链式前向星建树 
void add(int x, int y) {
   
	nex[++ tot] =
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值