牛客网 Treepath 树形dp || 思维

来源:互联网 发布:vmware fusion 知乎 编辑:程序博客网 时间:2024/04/28 00:50


题目链接

给定一棵n个点的树,问其中有多少条长度为偶数的路径。路径的长度为经过的边的条数。x到y与y到x被视为同一条路径。路径的起点与终点不能相同。

考虑树形dp,dp[i][0/1]分别表示从子树中到i结点的偶数路径和奇数路径有多少,那么有如下转移:
dp[i][0] += dp[u][1]
dp[i][1] += dp[u][0]。
但是发现对于那些跨子树的没考虑好,后来才想明白,其实跨子树的情况我们把他加到根结点当中在计数就可以了.
也就是
ans += dp[i][0] * dp[u][1]
ans += dp[i][1]*dp[u][0]。

#include<bits/stdc++.h>using namespace std;const int maxn = 2e5+5;typedef long long ll;ll dp[maxn][3],ans;int n;vector<int>vt[maxn];void dfs(int x,int f){    dp[x][0] = 1,dp[x][1] = 0;    for(int i = 0;i < vt[x].size();++i)    {        int v = vt[x][i];        if(v == f) continue;        dfs(v,x);        ans += dp[x][1] * dp[v][0];        ans += dp[x][0] * dp[v][1];        dp[x][0] += dp[v][1];        dp[x][1] += dp[v][0];    }    return ;}int main(){    while(scanf("%d",&n) != EOF)    {       for(int i = 0;i <= n;++i) vt[i].clear();        for(int i = 1;i < n;++i)        {            int x,y;            scanf("%d %d",&x,&y);            vt[x].push_back(y);            vt[y].push_back(x);        }        ans = 0;        dfs(1,-1);        printf("%lld\n",ans);    }    return 0;}/*71 21 32 42 53 63 741 21 31 451 21 31 42 5*/

另一种比较好的方法就是,考虑随便找一个根节点建树,记录深度,将所有偶数深度的结点拿出来放在一起,个数为a,奇数同理,个数为b,这样就保证了两个图当中任意两个结点之间的路径都为偶数,然后所有路径数为 a(a1)2+b(b1)2

#include<bits/stdc++.h>using namespace std;const int maxn = 2e5+5;typedef long long ll;vector<int>vt[maxn];ll a,b;int n;void dfs(int x,int f,int dep){    if(dep % 2 == 0) a++;    else b++;    for(int i = 0;i < vt[x].size();++i)    {        int v = vt[x][i];        if(v == f) continue;        dfs(v,x,dep+1);    }    return ;}int main(){    while(scanf("%d",&n) != EOF)    {       for(int i = 0;i <= n;++i) vt[i].clear();        for(int i = 1;i < n;++i)        {            int x,y;            scanf("%d %d",&x,&y);            vt[x].push_back(y);            vt[y].push_back(x);        }        dfs(1,-1,0);        //for(int i = 1;i <= n;++i)        //    ans += dp[i][0];        ll ans = a*(a-1)/2 + b*(b-1)/2;        printf("%lld\n",ans);    }    return 0;}