题目:
给定一棵无根树,假设它有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
思路:DFS一边可以找到一个节点的距离和,其他节点可以用该节点递推出来,在一边dfs就可以了。不过最后一组数据会爆栈,所以需要加点其他的东西。。。。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 100010
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define INF 1000000000
int n , k;
vector<int>v[maxn];
LL ans[maxn];
int num[maxn];
bool vis[maxn];
LL tmp = 0;
int DFS(int pos , int dis)
{
tmp += dis;
int up = v[pos].size();
int flag = 0;
for(int i = 0 ; i < up ; i ++)
{
if( !vis[v[pos][i]])
{
flag = 1;
vis[v[pos][i]] = 1;
num[pos] += DFS(v[pos][i] , dis + 1);
}
}
if(!flag) return 1;
else return num[pos] + 1;
}
void DFS2( int pos)
{
int up = v[pos].size();
for(int i = 0 ; i < up ; i ++)
{
if( !vis[v[pos][i]])
{
ans[v[pos][i]] = ans[pos] - num[v[pos][i]] + (n - num[v[pos][i]] - 2);
vis[v[pos][i]] = 1;
DFS2( v[pos][i] );
}
}
}
int main()
{
while(scanf("%d" , &n) != EOF)
{
if(n < 1) continue;
for(int i = 0 ; i < maxn ; i ++) v[i].clear();
tmp = 0;
mem(ans , 0);
mem(num , 0);
mem(vis , false);
int u , v2;
for(int i = 0 ; i < n - 1 ; i ++)
{
scanf("%d %d" , &u , &v2);
if(u > v2) swap(u , v2);
v[u].push_back(v2);
}
DFS(1 , 0);
ans[1] = tmp;
mem(vis , false);
DFS2(1);
for(int i = 1 ; i <= n ; i ++) printf("%I64d\n" , ans[i]);
}
return 0;
}