题目
给定一个有 𝑁 个点的树,每条边的长度有一个边权,现在定义 𝑑𝑖𝑠(𝑖,𝑗) 代表第 𝑖 个点到第 𝑗 个点的距离模 2 之后的结果。
问有多少 (𝑖,𝑗,𝑘) 满足,𝑑𝑖𝑠(𝑖,𝑗) = 𝑑𝑖𝑠(𝑗,𝑘) = 𝑑𝑖𝑠(𝑖,𝑘)。
解题思路
可以将两点的距离转换成到根节点的距离。可以任意选一个节点作为根节点,比如节点 1。 要么是 0,要么是 1。
同理,
要使 ,则要
。
同理,要使 ,则要
。
综上,当 时,由
。
使用 DFS 算法计算从根节点 1 到每个节点的距离,并统计每种距离的数目。
表示
的节点数。
根据数学的排列,得出答案为 。
C++代码
#include<iostream> #include<vector> using namespace std; vector<vector<vector<int>>> edges; vector<bool> vis; int cnt[3]; void dfs(int s, int d){ for(auto e : edges[s]){ if(!vis[e[0]]){ vis[e[0]] = true; int tmp = (d + e[1]) % 2; cnt[tmp] += 1; dfs(e[0], tmp); } } } int main(){ int n; cin >> n; edges.resize(n+1); int s, e, d; for(int i=0; i<n; ++i){ cin >> s >> e >> d; d %= 2; edges[s].push_back({e,d}); edges[e].push_back({s,d}); } vis.resize(n+1, false); vis[1] = true; cnt[0] += 1; // 根节点本身与自己的距离是 0 dfs(1,0); long long ans = 1LL*cnt[0]*cnt[0]*cnt[0] + 1LL*cnt[1]*cnt[1]*cnt[1]; cout << ans << endl; return 0; }