题目描述
现有一个 n 个点,n-1条边组成的树,其中 1 号点为根节点。
牛牛和牛妹在树上玩游戏,他们在游戏开始时分别在树上两个不同的节点上。
在游戏的每一轮,牛牛先走一步,而后牛妹走一步。他们只能走到没有人的空节点上。如果谁移动不了,就输掉了游戏。现在牛牛和牛妹决定随机选择他们分别的起点,于是他们想知道,有多少种游戏开始的方式,使得牛牛存在一种一定获胜的最优策略。
两种开始方式相同,当且仅当在两种开始方式中牛牛,牛妹的开始位置是分别相同的,否则开始方式就被视作不同的。
输入描述:
第一行输入为一个整数 n,代表树的点数。
第二行n-1个整数
,分别代表2,3,…,n号点的父节点编号。
输出描述:
一行一个整数,代表答案。
输入
3
1 2
2
1
30
1 1 2 1 2 1 3 2 3 4 2 3 1 2 3 4 2 4 5 6 3 4 12 12 12 13 13 13 13
输出
2
0
428
说明
- 当且仅当牛牛在1号点,牛妹在3号点,或者牛牛在3号点,牛妹在1号点时,牛牛才获胜。
- 由于无论如何牛牛都无路可走,因此必然牛妹获胜。
- QwQ
备注:
题解
- 首先我们知道,如果A输掉,那么A唯一的一条边上有人,即A一定在叶子上
- 设两个人初始距离为D,每人移动后D+1或者D-1
- 假设最开始D为偶数,那么当牛牛移动后,D始终为偶数,牛妹妹移动后,D始终为奇数
- 已知当两人相邻的时候D=1,是奇数,也就是说,D=1的时候,开始走的人输掉。
- 那么经过上面分析,我们就可以知道:如果最初D为偶数,牛牛获胜,反之如果最初为奇数,牛妹妹获胜。
- 那么答案就很显然了,只需要求出深度为奇数的点和偶数的点的数量即可
注意
- 注意到题目有一个特殊的范围: 。
- 说实话这个没啥用,正解应该是跑DFS,但是由于这个条件存在,导致了任意一个点确定下来的时候,他的父节点一定在他前面确定。也就可以不用DFS了,输入的时候直接就已经知道父节点的深度了。
- 显然这个额外条件导致数据很水
AC-Code
#include <bits/stdc++.h>
using namespace std;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
const int maxn = 1e6 + 7;
ll cnt[2]; // 当前节点为根的子树
vector<int>G[maxn];
void dfs(int now, int d) {
for (auto v : G[now]) {
dfs(v, d + 1);
}
++cnt[d & 1];
}
int main() {
ios;
int n; while (cin >> n) {
cnt[0] = cnt[1] = 0;
for(int i = 1; i <= n; ++i) G[i].clear();
for (int i = 2; i <= n; ++i) {
int fa; cin >> fa;
G[fa].push_back(i);
}
dfs(1, 0);
cout << cnt[1] * (cnt[1] - 1) + cnt[0] * (cnt[0] - 1) << endl;
}
return 0;
}
/*
10
10 9 8 1 3 6 9 1 5
48
*/
/*
10
1 1 2 2 4 5 3 6 8
40
*/