The city of Thunder has many houses and they are powered by lightning. Two houses may be interconnected by a wire. The wires connect the houses such that there is exactly one path from one house to any other house in the city. Each house has a large battery that can store infinite electrical energy.
Everyday, several lightnings strike several houses. These lightnings are very unusual, when it strikes, it strikes two houses simultaneously: one house (A) with a red lightning and the other house (B) with a blue lightning. After the strikes, every house along the path from A to B (inclusive) will receive a certain amount of electrical energy which is then added to the house's battery.
The mayor of Thunder city wants a report on the stored electrical energy for every house at the end of the month and the owner of each house has to pay taxes for that. To prevent the owners report invalid energy stored in their house battery (because they want less tax to pay), you are asked to produce a correct report based on the observed lightnings of the current month. At the beginning of the month, the energy reading on the battery of each house is 0.
Input
The first line of input contains an integer T (T10), the number of cases. Each case begins with an integerN (2
N
50, 000), the number of houses in the Thunder city. The next N - 1 lines contain the wire connections where each line will consist of two integers X and Y which means house X is connected with houseY. The house number is from 0 to N - 1. The next line will contain a number Q (1
Q
50, 000) which denotes the number of observed lightning strikes. The next Q lines describe the unusual lightnings happened during the month. Each line will consist of three integers A, B, C which tells that a red lightning strikes house Aand a blue lightning strikes house B and the power transferred is C (at most 100) based on the reading of a special lightning instrument.
Output
For each case, output ``Case #X:" (without quote) where X is the case number and N lines where each line is the electrical energy reading on the battery of each house from house 0 to house N - 1 at the end of the month.
Sample Input
1 9 0 1 1 2 2 3 2 4 2 7 7 8 7 6 6 5 5 1 4 10 3 5 3 0 8 5 1 6 10 4 4 100
Sample Output
Case #1: 5 25 28 3 110 3 13 18 5
题意很简单,给你一棵树。先给出很多操作(x,y)即把x到y路径上的点权都加上z。最后输出每个点最终的点权。
方法是求出x,y的最近公共祖先p=lca(x,y);(本题可以用tarjan,也可以用rmq)
对于每一次操作,执行以下几步;
w[x]+=z;
w[y]+=z;
w[p]-=z;
w[fa[p]]-=z;
其中fa[x]为x的父亲,fa[root]随便设一个值,比如fa[root]=n+1;
之后对图做一次dfs在回溯的时候累加上权值就可以了。具体看代码,最好用手画个例子推一下。
#include<cstdio>
#include<cstring>
#include<vector>
#include<cstdlib>
#define maxn 50009
using namespace std;
vector<int>G[maxn];
int a[maxn][20];
int tin[maxn],tout[maxn],t,ans[maxn],w[maxn],pa[maxn];
int n,m;
void dfs(int x,int px)
{
tin[x]=t++;
a[x][0]=px;
if(x)pa[x]=px;
else pa[x]=n+1;
for(int i=1;1<<i<n/2;i++)
a[x][i]=a[a[x][i-1]][i-1];
for(int i=0;i<G[x].size();i++)
{
int v=G[x][i];
if(v!=px)
dfs(v,x);
}
tout[x]=t++;
}
bool act(int x,int y)
{
return tin[x]<=tin[y]&&tout[y]<=tout[x];
}
int log2(int x)
{
int i=0;
while(1<<i<=x)i++;
return i-1;
}
int lca(int x,int y)
{
if(act(x,y))return x;
if(act(y,x))return y;
for(int i=log2(n/2);i>=0;i--)
if(!act(a[x][i],y))
x=a[x][i];
return a[x][0];
}
void init()
{
memset(a,0,sizeof(a));
t=0;dfs(0,0);
}
void dp(int cur,int fa)
{
for(int i=0;i<G[cur].size();i++)
{
int v=G[cur][i];
if(v!=fa){
dp(v,cur);
ans[cur]+=ans[v]; //先处理子树,再用子树的结果去累加
}
}
ans[cur]+=w[cur]; //最后加上自己的权值
}
int main()
{
int tt;
scanf("%d",&tt);
int cot=0;
while(tt--)
{
scanf("%d",&n);cot++;
for(int i=0;i<=n;i++)G[i].clear();
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
init();
scanf("%d",&m);
memset(w,0,sizeof(w));
memset(ans,0,sizeof(ans));
for(int i=0;i<m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
w[x]+=z;
w[y]+=z;
w[lca(x,y)]-=z;
w[pa[lca(x,y)]]-=z;
}
dp(0,0);
printf("Case #%d:\n",cot);
for(int i=0;i<n;i++)
printf("%d\n",ans[i]);
}
}