题意:
Description
给定一棵有n个顶点的树,你需要统计出树上所有长度为奇数的路径数量。路径长度为经过边的条数。s 到 t 和 t 到 s视作相同。
Input
第一行为测试数据组数T( 1 <= T <= 5).每组测试数据:第一行有一个整数n(1 <= n <= 1e5),表示顶点数。接下来n - 1 行 每行两个整数u, v,表示u, v之间存在一条边。
Output
一个整数, 路径长度为奇数的数量。
Sample Input
2
2
1 2
4
1 2
2 3
1 4
Sample Output
1
4
思路:
这道题典型的树形dp题,规定1节点为root,dp【i】【0】代表以i为根节点的子树的奇数子节点个数,dp【i】【1】代表以i为根节点的子树的偶数子节点个数,dp【1】【0】+dp【1】【0】✖️dp【1】【1】即为答案
代码:
#include <stdio.h>
#include <vector>
#include <string.h>
#define ll long long
using namespace std;
int n;
vector <int>zcy[100005];
int dp[100005][2];
void dfs(int inx, int father) {
for (int i = 0; i < zcy[inx].size(); i++) {
int ii = zcy[inx][i];
if(ii ==father) continue;
dfs(ii, inx);
dp[inx][0] += dp[ii][1] + 1;
dp[inx][1] += dp[ii][0];
}
}
int main() {
int T, a, b;
scanf("%d", &T);
while(T--) {
memset(dp, 0, sizeof(dp));
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
zcy[i].clear();
}
for (int i = 0; i < n - 1; i++) {
scanf("%d%d", &a, &b);
zcy[a].push_back(b);
zcy[b].push_back(a);
}
dfs(1, 0);
ll ans = (ll)dp[1][0] * (dp[1][1] + 1);
printf("%lld\n", ans);
}
return 0;
}
如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢