UVALIVE 5061 - Lightning Energy Report(LCA)

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 (T<=10), the number of cases. Each case begins with an integer N (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 house Y. 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 A and 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
树上的区间问题, 可以转换成LCA问题求解。
举个例子, 假设查询a, b,c d = lca(a, b) 则 [a - d] += c , [b - d] += c, d -= c; 
这样在查询时只用a += c, b += c, d -= c, parter(d) -= c (这里指这个点上的值,初始化为0)既可, 复杂度为lca(a, b)的复杂度。
这样在最后只用一次对树的遍历,就可得到答案了。
如果不是树上的区间问题, 比如是图上的, 可以求图的双连通分量, 把图变成树, 然后就和这题一样了。
还有其他区间问题,可以考虑怎么建树, 然后用LCA求解问题。 当然RMQ还是有很多优秀的算法可以直接用,不过有时候问题较复杂,可以考虑把问题转换。
View Code
1 const int MAXN = 50001;
2  const int MAXLOGN = 20;
3 vector<vector<int> >g;
4  int p[MAXN][MAXLOGN], L[MAXN];
5  int val[MAXN];
6
7  void dfs(int u, int pa, int d) {
8 p[u][0] = pa; L[u] = d;
9 for (int i = 0; i < g[u].size(); ++i) {
10 if (g[u][i] != pa) {
11 dfs(g[u][i], u, d + 1);
12 }
13 }
14 }
15
16  void process(int N) {
17 for (int i = 0; i < N; ++i) {
18 for (int j = 0; (1 << j) < N; ++j) {
19 p[i][j] = -1;
20 }
21 }
22 dfs(0, 0, 0);
23 for (int j = 1; (1 << j) < N; ++j) {
24 for (int i = 0; i < N; ++i) {
25 if (p[i][j-1] != -1) {
26 p[i][j] = p[p[i][j-1]][j-1];
27 }
28 }
29 }
30 }
31
32  int query(int a, int b) {
33 if (L[a] < L[b]) swap(a, b);
34 int tmp = 1;
35 for (; (1 << tmp) <= L[a]; ++tmp);
36 --tmp;
37 for (int i = tmp; i >= 0; --i)
38 if (L[a] - (1 << i) >= L[b])
39 a = p[a][i];
40 if (a == b) return a;
41 for (int i = tmp; i >= 0; --i)
42 if (p[a][i] != -1 && p[a][i] != p[b][i])
43 a = p[a][i], b = p[b][i];
44 return p[a][0];
45 }
46
47 void add(int u, int v, int c) {
48 int lca = query(u, v);
49 val[u] += c, val[v] += c;
50 val[lca] -= c;
51 if (p[lca][0] != lca) {
52 val[p[lca][0]] -= c;
53 }
54 }
55
56 int cal(int u, int pa) {
57 for (int i = 0; i < g[u].size(); ++i) {
58 if (g[u][i] != pa)
59 val[u] += cal(g[u][i], u);
60 }
61 return val[u];
62 }
63
64 int main () {
65 int T = nextInt();
66 for (int nCase = 1; nCase <= T; ++nCase) {
67 int N = nextInt();
68 g.clear(); g.resize(N);
69 for (int i = 0; i < N - 1; ++i) {
70 int u = nextInt();
71 int v = nextInt();
72 g[u].push_back(v);
73 g[v].push_back(u);
74 }
75 process(N);
76 memset(val, 0, N << 2);
77 int Q = nextInt();
78 for (int i = 0; i < Q; ++i) {
79 int u = nextInt();
80 int v = nextInt();
81 int c = nextInt();
82 add(u, v, c);
83 }
84 cal(0, 0);
85 printf("Case #%d:\n", nCase);
86 for (int i = 0; i < N; ++i) {
87 printf("%d\n", val[i]);
88 }
89 }
90 return 0;
91 }
posted on 2011-06-07 11:12  cegr  阅读(334)  评论(0编辑  收藏  举报