树学 题解

树学

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

换根dp,维护dp数组:以某结点为根的时候的答案
维护_size数组:某结点为根的子树大小
第二次dfs的时候换根进行旋转就可以了,类似于AVL树和Splay Tree的旋转

#include <bits/stdc++.h>
using namespace std;
const int N=1000100;
#define ll long long
ll _size[N];
ll dp[N];
ll ans=1e17;
struct node
{
    int v,next;
}e[N<<1];
int cnt=0;
int head[N];
void add(int u,int v)
{
    e[++cnt].v=v;
    e[cnt].next=head[u];
    head[u]=cnt;
}
void dfs(int u,int pre)
{
    _size[u]=1;
    for(int i=head[u];i;i=e[i].next)
    {
        int to=e[i].v;
        if(to==pre) continue;
        dfs(to,u);
        _size[u]+=_size[to];
        dp[u]+=dp[to]+_size[to];
    }
}
void dfs2(int u,int pre)
{
    ans=min(ans,dp[u]);
    for(int i=head[u];i;i=e[i].next)
    {
        int to=e[i].v;
        if(to==pre) continue;
        int p1=_size[u];
        int p2=_size[to];
        int P1=dp[u];
        int P2=dp[to];
        dp[u]-=(dp[to]+_size[to]);
        _size[u]-=_size[to];
        _size[to]+=_size[u];
        dp[to]+=(dp[u]+_size[u]);
        dfs2(to,u);
        _size[u]=p1;
        _size[to]=p2;
        dp[u]=P1;
        dp[to]=P2;
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    dfs(1,-1);
    dfs2(1,-1);
    printf("%lld\n",ans);
}
全部评论

相关推荐

10-13 22:56
门头沟学院 C++
rt,鼠鼠的浪潮网签明天过期,鼠鼠是山东人,好像自己也能接受。之前的面试大厂基本挂干净了,剩下小米二面后在泡,问了下面试官没有挂,但要泡。还有海信似乎也通过了,不过在深圳,鼠鼠也不是很想去。其它还有一些公司应该陆陆续续还有一些面试,现在有些纠结是直接签了还是再等再面呢?大佬们能不能给鼠鼠提一些意见,万分感谢!!!
牛客78696106...:浪潮可不是开摆,当初我还是开发的时候我组长跟我说他们组有段时间天天1,2点走,早上5点就来,全组肝出来心肌炎,浪潮挣钱省立花可不是说说,当然也看部门,但是浪潮普遍就那dio样,而且你算下时薪就知道不高,没事也是9点半走,不然算你旷工
投递小米集团等公司10个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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