【每日一题】Treepath(树形dp)

Treepath

https://ac.nowcoder.com/acm/problem/14248

Solution
记得寒假牛客有道题就是这道题的扩展,好像是求路径数目+博弈论。

表示以 i 为根的子树到 i 的距离为偶数/奇数的数目。
那么在dfs过程中,以 u 为根且子结点为 v 对答案的贡献是:

(子结点与父节点距离相差1,所以应操作不同奇偶性)
当然遍历完也需要把 v 的路径数合并到 u里面去:

Code

#include<bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ll long long
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a =
(a*a)%p;b >>= 1;}return ans%p;}
const int mo=998244353; const int mod=1000000007;

const int manx=1e5+5;

vector<ll>g[manx];
ll ans;  ll dp[manx][2];

void dfs(ll u,ll pre){
    dp[u][0]=1;
    for(auto v: g[u]){
        if(v==pre) continue;
        dfs(v,u);
        ans+=dp[v][0]*dp[u][1];
        ans+=dp[v][1]*dp[u][0];
        dp[u][0]+=dp[v][1];
        dp[u][1]+=dp[v][0];
    }
}

int main(){
    ll n=read();
    for(int i=1;i<n;i++){
        ll u=read(),v=read();
        g[u].pb(v); g[v].pb(u);
    }
    dfs(1,0);
    cout<<ans;
    return 0;
}
全部评论

相关推荐

ArisRobert:统一解释一下,第4点的意思是,公司按需通知员工,没被通知到的员工是没法去上班的,所以只要没被通知到,就自动离职。就是一种比较抽象的裁员。
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务