zoukankan      html  css  js  c++  java
  • 1405 树的距离之和 二次扫描换根法

    1405 树的距离之和

    题意:给定一棵无根树,假设它有n个节点,节点编号从1到n, 求任意两点之间的距离(最短路径)之和。

    思路:开个数组size记录每个节点和它子节点集合的大小,开个sum用来记录dfs过程中从根节点到子节点的距离,也就是距离前缀和,f用来记录每个节点到其他所有节点的距离。

     

    2次dfs原因:

    第一次:dfs我们可以从根节点向下求根节点到每个子节点的前缀和,用sum记录然后我们把每个节点的sum给了f[1]就求出根节点到所有节点的距离和了。同时回溯时,求出每个节点子集的大小,用size记录。

    第二次dfs:已知根节点1到其他节点的距离和,然后还已知每个节点子集的大小,该怎么求其余每个节点到其他节点的距离和?可以利用根的转移。

     

    对于遍历到的任意一个节点 i,对于与之相邻的节点 j 来说,答案贡献由 i 到 j 转移首先减小了 size[j]1size[j]∗1,

    同时增加了 (nsize[j])1(n−size[j])∗1,因此可以直接得到f[j]=f[i]+nsize[j]2f[j]=f[i]+n−size[j]∗2。

    如图,如果根转移到节点2,距离首先要减少size[2]*1,然后要增加(n-size[2])*1,因为根变为节点2,节点一到节点二子集的所有距离要消失,也就是红色部分(size[v]),要增加从节点2到节点一子集的距离也就是绿色部分(n-size[v]),得状态转移方程如下:

    f[v]=f[u]+n-size[v]*2

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int maxn=1e5+10;
    int head[2*maxn],ver[2*maxn],nxt[2*maxn];
    int tot=0;
    int n;
    ll sum[maxn],size[maxn],f[maxn];
    void add(int u,int v)
    {
        ver[++tot]=v;
        nxt[tot]=head[u];
        head[u]=tot;
    }
    
    void dfs1(int u,int fa)
    {
        size[u]=1;
        for(int i=head[u]; i; i=nxt[i])
        {
            int v=ver[i];
            if(v==fa) continue;
            sum[v]=sum[u]+1;
            f[1]+=sum[v];
            dfs1(v,u);
            size[u]+=size[v];
        }
    }
    
    void dfs2(int u,int fa)
    {
        for(int i=head[u]; i; i=nxt[i])
        {
            int v=ver[i];
            if(v==fa) continue;
            f[v]=f[u]+n-2*size[v];
            dfs2(v,u);
        }
    
    
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1; i<=n-1; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        dfs1(1,0);
        dfs2(1,0);
        for(int i=1; i<=n; i++)
            printf("%lld
    ",f[i]);
    }
  • 相关阅读:
    centos7 hpc高性能计算集群配置(无密码访问、nfs文件共享)
    dbGrid、cxGrid下拉列表做单、多列更新的三种实现方式
    delphi指针简单入门
    Delphi USB摄像头
    Delphi USB摄像头
    DelphiXE环境认知(第一章 Project Options)
    程序缩小到托盘后系统就无法关机(解决方案)
    TNotifyEvent
    关于Delphi在定义了函数进行调用时显示undeclared identifier的问题
    listview增加一行后,显示最后一条数据,进度条显示最底
  • 原文地址:https://www.cnblogs.com/dongdong25800/p/11127307.html
Copyright © 2011-2022 走看看