题目:click
题意:问一棵树上的i点到其他点的距离总和。
先考虑一个点i,可以看出一条路是一边是来自子节点的距离,一个是来自父节点的距离,树上dp,dp[i][0]来自子节点的总距离,dp[i][1]来自父节点的总距离,预先处理出子节点和父节点的个数,其中可以化简过程作总和,已经分开写了我就没改了。这里代码有点繁杂,注意细节。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 50100*4
using namespace std;
typedef long long ll;
const int mod=1e9+7;
vector<int>hh[100100];
bool vis[100100];
ll dp[100100][2];
ll sonsize[100100]={0};
ll fsonsize[100100]={0};
inline void dfsson(int u,int f)
{
vis[u]=1;
sonsize[u]=1;
for(int i=0;i<hh[u].size();i++)
{
int v=hh[u][i];
if(v==f||vis[v])
continue;
dfsson(v,u);
sonsize[u]+=sonsize[v];
}
}
inline void dfs1(int u,int f)
{
vis[u]=1;
dp[u][0]=0;
bool flag=false;
for(int i=0;i<hh[u].size();i++)
{
int v=hh[u][i];
if(v==f||vis[v])
continue;
flag=true;
dfs1(v,u);
dp[u][0]+=dp[v][0]+sonsize[v];
}
}
inline void dfsfson(int u,int f)
{
vis[u]=1;
for(int i=0;i<hh[u].size();i++)
{
int v=hh[u][i];
if(v==f||vis[v])
continue;
fsonsize[v]=sonsize[u]-sonsize[v]+fsonsize[u];
dfsfson(v,u);
}
}
inline void dfs2(int u,int f)
{
vis[u]=1;
for(int i=0;i<hh[u].size();i++)
{
int v=hh[u][i];
if(v==f||vis[v])
continue;
dp[v][1]=dp[u][0]-dp[v][0]-sonsize[v]+sonsize[u]-sonsize[v]+dp[u][1]+fsonsize[u];
dfs2(v,u);
}
}
int main()
{
memset(dp,0,sizeof(dp));
int n,i,j,k;
scanf("%d",&n);
for(i=0;i<n-1;i++)
{
int x,y;
scanf("%d %d",&x,&y);
hh[x].push_back(y);
hh[y].push_back(x);
}
memset(vis,false,sizeof(vis));
dfsson(1,0);
memset(vis,false,sizeof(vis));
dfs1(1,0);
memset(vis,false,sizeof(vis));
fsonsize[1]=fsonsize[0]=0;
dfsfson(1,0);
memset(vis,false,sizeof(vis));
dfs2(1,0);
for(i=1;i<=n;i++)
{
ll temp=dp[i][0]+dp[i][1];
printf("%I64d\n",temp);
}
return 0;
}