您的位置:首页 > 其它

51nod 1405 树的距离和

2017-07-28 20:32 393 查看
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1405

题意:

有n个节点的无根树,求每个节点分别到其他n-1个节点的距离之和。

思路:

设dp[x]表示节点x到其他n-1个节点的距离和。

一个dp[x]是很好求的,把x当成根,一遍dfs,把所有点的深度加起来,就可以求出dp[x]。

得知dp[x]如何求得dp[y]呢?此时x是父节点,y是儿子节点。我们再增加一个儿子节点z,这三个点的联系为y–x–z。知道dp[x],求dp[y],那么,等于dp[y] = dp[x]-son[y]+(n-son[y]),dp[x]即减去y子节点的个数,再加上非y子节点得到个数。

代码:

#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>

using namespace std;

const int maxn = 1e5+5;
vector<int> edges[maxn];

int n, a, b;
bool vis[maxn];
int son[maxn];
long long dp[maxn];

void dfs1(int rt, int depth){
int len = edges[rt].size();
vis[rt] = true;
son[rt] = 1;
dp[1] += depth;
for(int i=0; i<len; ++i){
int sn = edges[rt][i];
if(!vis[sn]){
dfs1(sn, depth+1);
son[rt] += son[sn];
}
}
}

void dfs2(int rt){
vis[rt] = true;
int len = edges[rt].size();
for(int i=0; i<len; ++i){
int sn = edges[rt][i];
if(!vis[sn]){
dp[sn] = dp[rt]+n-son[sn]*2;
dfs2(sn);
}
}
}

int main(){
scanf("%d", &n);
for(int i=0; i<n-1; ++i) {
scanf("%d%d", &a, &b);
edges[a].push_back(b);
edges[b].push_back(a);
}
dfs1(1, 0);
memset(vis, 0, sizeof(vis));
dfs2(1);
for(int i=1; i<=n; ++i){
printf("%lld\n", dp[i]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: