【每日一题】Treepath

戳我传送


思路:


方法一:因为每条边的权值都是一样,所以可以用LCA求得每个结点想对于根结点1的深度,在这里深度就是距离。从偶数层到偶数层和从奇数层到奇数层的路径都是偶数。这里可以用链式向前星存图,然后dfs统计有多少个奇数层a和偶数层b,不必要区分偶数层和奇数层,答案就是图片说明 +图片说明 。如果1e5-1个结点都连在根结点1上,这时的答案最大,需要用long long。
复杂度图片说明 (log n)。
Code戳我

方法二:设f[i][0/1]表示以i为根的子树中,与根节点i的距离为偶数(0)奇数(1)的点的数量。
转移方程显然是f[u][x]+=f[v][x^1],f[u][x^1]+=f[v][x]。
答案就包括父结点u子树集合里到u为偶数的点数 * v子树集合里到u为奇数的点数和父结点u子树集合里到u为奇数的点数 * v子树集合里到u为偶数的点数,这些方案都经过子树的根u。一定不能先更新f再求ans,因为两个点匹配一定要在两个不同的集合,在一个集合就会出现重复。
复杂度图片说明 (log n)。


Code:


#include<bits/stdc++.h>
using namespace std;
int read(){
    int x=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x;
}
int to[200005],Next[200005],head[100005],tot;
void add(int x,int y) {
    to[++tot]=y;
    Next[tot]=head[x];
    head[x]=tot;
}
long long ans;
int f[100005][2];
void dfs(int u,int fa) {
    f[u][0]=1;
    for(int i=head[u];i;i=Next[i]) {
        int y=to[i];
        if(y==fa) continue;
        dfs(y,u);
        ans+=f[u][1]*f[y][0];
        ans+=f[u][0]*f[y][1];
        f[u][0]+=f[y][1];
        f[u][1]+=f[y][0];
    }
}
int main() {
    int n=read();
    for(int i=2;i<=n;++i) {
        int x=read(),y=read();
        add(x,y);
        add(y,x);
    }
    dfs(1,0);
    cout<<ans<<endl;
}
每日一题 文章被收录于专栏

牛客每日一题

全部评论

相关推荐

12-27 22:21
门头沟学院 Java
点赞 评论 收藏
分享
10-31 21:01
武汉大学 Java
lulululula...:仅仅按我个人的经历来看,大厂其实很少特别关注微服务,一般对微服务架构,限流熔断降级的概念了解就行,简历不写也不容易被问到。现在这个势头不如站点agent应用,比如做做mcp,rag,r对话agent,记忆管理之类的,说不定可以蹭上一波热度,进公司虽然可能还是干agent的杂活,但是可以学一学组内的业务和技术了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务