51 nod 1405 树的距离之和

Posted Przz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51 nod 1405 树的距离之和相关的知识,希望对你有一定的参考价值。

 

1405 树的距离之和技术分享

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
 
给定一棵无根树,假设它有n个节点,节点编号从1到n, 求任意两点之间的距离(最短路径)之和。
Input
第一行包含一个正整数n (n <= 100000),表示节点个数。
后面(n - 1)行,每行两个整数表示树的边。
Output
每行一个整数,第i(i = 1,2,...n)行表示所有节点到第i个点的距离之和。
Input示例
4
1 2
3 2
4 2
Output示例
5
3
5
5

 

 

/*
51 nod 1405 树的距离之和

problem:
给定一棵无根树,假设它有n个节点,节点编号从1到n, 对于每个i求所有点到i的和。

solve:
假设已经知道了所有点到u的和, 对于它右儿子v的和,可以发现增加了Size[左子树]条uv边.减少了Size[v]条uv边
所以先求出所有点到1的和,然后可以推出其它所有点

hhh-2016/09/13-20:15:59
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <math.h>
#include <queue>
#include <set>
#include <map>
#define lson  i<<1
#define rson  i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define scanfi(a) scanf("%d",&a)
#define scanfs(a) scanf("%s",a)
#define scanfl(a) scanf("%I64d",&a)
#define scanfd(a) scanf("%lf",&a)
#define key_val ch[ch[root][1]][0]
#define eps 1e-7
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 100110;

template<class T> void read(T&num)
{
    char CH;
    bool F=false;
    for(CH=getchar(); CH<‘0‘||CH>‘9‘; F= CH==‘-‘,CH=getchar());
    for(num=0; CH>=‘0‘&&CH<=‘9‘; num=num*10+CH-‘0‘,CH=getchar());
    F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p)
{
    if(!p)
    {
        puts("0");
        return;
    }
    while(p) stk[++ tp] = p%10, p/=10;
    while(tp) putchar(stk[tp--] + ‘0‘);
    putchar(‘\n‘);
}

ll ans[maxn];
struct node
{
    int to,next;
}edge[maxn <<2];

int tot,n;
int head[maxn];
int Size[maxn];
ll f[maxn];
void add_edge(int u,int v)
{
    edge[tot].to = v,edge[tot].next = head[u],head[u] = tot ++;
}

void dfs(int u,ll len,int pre)
{
    f[u] = len;
    Size[u] = 1;
    for(int i = head[u]; i != -1;i = edge[i].next )
    {
        int v = edge[i].to;
        if(v == pre)
            continue;
        dfs(v,len+1,u);
        Size[u] += Size[v];
    }
}

void solve(int u,ll tans,int pre)
{
    ans[u] = tans;
    for(int i = head[u];i != -1;i = edge[i].next)
    {
        int v = edge[i].to;
        if(v == pre)
            continue;
        ll t = n-Size[v]*2;
        solve(v, (ll)tans + t,u);
    }
}

void init()
{
    tot = 0;
    clr(head,-1);
}

int main()
{
    int u,v;
    while(scanfi(n) != EOF)
    {
        init();
        for(int i = 1;i < n;i++)
        {
            scanfi(u),scanfi(v);
            add_edge(u,v);
            add_edge(v,u);
        }
        dfs(1,0,-1);
        ll ta = 0;
        for(int i =1;i <= n;i++)
          ta += f[i];
        solve(1,ta,-1);
        for(int i = 1;i <= n;i++)
        {
            print(ans[i]);
        }
    }
}

  

以上是关于51 nod 1405 树的距离之和的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1405 树的距离之和(dfs)

51nod 1405 树的距离之和 树形dp

[51NOD1405] 树的距离之和(树DP)

51Nod 1405 树的距离之和 (dfs)

51Nod 1737 配对(树的重心)

51Nod1405树上距离和 二次扫描与换根法