简单的分类讨论,存储每个结点的父亲fa[i],深度dep[i];整棵树的最大深度maxndep;以及深度为i的结点的集合mem[i]
#include<iostream>
#include<vector>
using namespace std;
const int N = 1e5 + 5;
int fa[N], dep[N], maxndep, ans;
vector<int> mem[N], nxt[N];
void build(int idx, int f)
{
for (int i = 0; i < nxt[idx].size(); i++)
{
if (nxt[idx][i] != f)
{
fa[nxt[idx][i]] = idx;
dep[nxt[idx][i]] = dep[idx] + 1;
mem[dep[idx] + 1].push_back(nxt[idx][i]);
maxndep = max(maxndep, dep[idx] + 1);
build(nxt[idx][i], idx);
}
}
}
int main()
{
int n; cin >> n;
for (int i = 1; i < n; i++)
{
int a, b; cin >> a >> b;
nxt[a].push_back(b);
nxt[b].push_back(a);
}
dep[1] = 1; mem[1].push_back(1); build(1, 0);
}
另外先看第三层所有结点的父亲是否相同(samefa3)
samefa4同理。后面有用
bool samefa3 = true, samefa4 = true;
if (maxndep < 3) samefa3 = false;
if (maxndep < 4) samefa4 = false;
for (int i = 1; i < mem[3].size(); i++)
{
if (fa[mem[3][i]] != fa[mem[3][0]])
{
samefa3 = false; break;
}
}
for (int i = 1; i < mem[4].size(); i++)
{
if (fa[mem[4][i]] != fa[mem[4][0]])
{
samefa4 = false; break;
}
}
易知只有深度为1或2或3的结点有可能成为符合要求的结点。
对于第一层的结点(即根结点),只要maxndep <= 3, 它就是符合要求的。
if (maxndep <= 3)
{
ans += mem[1].size();
}
对于第二层的结点a,它到第一层的距离一定是1,因为第一层只有一个结点;第二层的结点之间的距离一定是2;而它到第三层结点b的距离有两种情况:一、a是b的父亲,距离为1 二、a不是b的父亲,距离为3
因此当maxndep == 2时,第二层所有结点均满足要求
if (maxndep == 2)
{
ans += mem[2].size();
}
当3 <= maxndep <= 4时,如果第三层的所有结点的父亲都相同,那么那个父亲结点满足要求。否则第二层就没有满足要求的点了。
else if (maxndep <= 4 && samefa3)
{
ans += 1;
}
对于第三层的结点,分析方法和第二层的一样。唯一不同的是第一层一定只有1个结点,但第二层不一样,要加一个判断条件
if (maxndep == 3 && mem[2].size() == 1)
{
ans += mem[3].size();
}
else if (maxndep <= 5 && mem[2].size() == 1 && samefa4)
{
ans += 1;
}