哈理工第八届校团队赛C树上路径计数

题意:

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;
}

转载请注明出处!!!

如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢

猜你喜欢

转载自blog.csdn.net/Ivan_zcy/article/details/84945584
今日推荐