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]);
        }
    }
}

  

时间: 2024-08-08 09:41:44

51 nod 1405 树的距离之和的相关文章

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

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

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

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1405 中文题面不解释了,两次dfs,第一次自下向上,第二次自上向下. ans[i]表示i节点的答案,cnt[i]表示i节点为root的子树的节点个数,d[i]表示i节点为root的子树的答案. 1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algor

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

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1405 (1)我们给树规定一个根.假设所有节点编号是0-(n-1),我们可以简单地把0当作根,这样下来父子关系就确定了. (2)定义数组num[x]表示以节点x为根的子树有多少个节点,dp[x]是我们所求的--所有节点到节点x的距离之和. (3)在步骤(1)中,其实我们同时可以计算出 num[x],还可以计算出每个节点的深度(每个到根节点0的距离),累加全部节点

51 nod 1766 树上的最远点对(线段树+lca)

1766 树上的最远点对 基准时间限制:3 秒 空间限制:524288 KB 分值: 80 难度:5级算法题 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即你需要求出max{dis(i,j) |a<=i<=b,c<=j<=d} (PS 建议使用读入优化) Input 第一行一个数字 n n<=100000. 第二行到第n行每行三个数字描述路的情况, x,y,z (1<=x,y<=n,1<

51 nod 1394 1394 差和问题(线段树)

1394 差和问题基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 有一个多重集合S(即里面元素可以有重复),初始状态下有n个元素,对他进行如下操作: 1.向S里面添加一个值为v的元素.输入格式为1 v 2.向S里面删除一个值为v的元素.输入格式为2 v 3.询问S里面的元素两两之差绝对值之和.输入格式为3 对于样例, 操作3,|1-2|+|1-3|+|2-3|=4 操作1 4之后,集合中的数字为1 2 3 4 操作3,|1-2|+|1-3|+|2-3|+|1-

51 nod 1188 最大公约数之和 V2

1188 最大公约数之和 V2 题目来源: UVA 基准时间限制:2 秒 空间限制:262144 KB 分值: 160 难度:6级算法题 给出一个数N,输出小于等于N的所有数,两两之间的最大公约数之和. 相当于计算这段程序(程序中的gcd(i,j)表示i与j的最大公约数): G=0; for(i=1;i<N;i++) for(j=i+1;j<=N;j++) { G+=gcd(i,j); } Input 第1行:1个数T,表示后面用作输入测试的数的数量.(1 <= T <= 5000

51 nod 1427 文明 (并查集 + 树的直径)

1427 文明 题目来源: CodeForces 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 安德鲁在玩一个叫“文明”的游戏.大妈正在帮助他. 这个游戏里面有n个城市和m条双向的道路.城市从1到n编号.对于每一对城市,他们之间要么有唯一的一条道路,要么就是不可互达.一条道路的定义是一个包含不同城市的序列 v1, v2,...,vk ,  vi  和  vi+1 (1≤ i < k)之间有直接的一条道路相连.这条道路的长度是k-1.两个城市在同一区域的

51 nod 1681 公共祖先 (主席树+dfs序)

1681 公共祖先 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另一个未知的平行宇宙,这n人的祖辈关系仍然是树形结构,但他们相互之间的关系却完全不同了,原来的祖先可能变成了后代,后代变成的同辈…… 两个人的亲密度定义为在这两个平行宇宙有多少人一直是他们的公共祖先. 整个家族的亲密度定义为任意两个人亲密度的总和. Input 第一行一个数n(1<=n<=100000)

树的距离

树的距离 题目大意:wyf非常喜欢树.一棵有根数树上有N个节点,1号点是他的根,每条边都有一个距离,而wyf是个爱问奇怪问题的熊孩子,他想知道对于某个点x,以x为根的子树上,所有与x距离大于等于k的点与x的距离之和.N<=2e5 思路:可以考虑离线算法,我们先将树dfs一遍,我们按dfs序在w中保存各个节点的深度的和序号,L[x],R[x],dis[x]分别表示以x为根的子树对应的dfs序的左右端点,以及x的深度.对每个操作q我们记录子树根节点,和v值,v=dis[x]+k.然后我们将w按节点深