其实这道题其实可以转化为这样一个问题

给定n-1对点,将这两点x,y间简单路径上的点(包括起点终点)权值+1

(最后再把除了起点外的点的权值-1,注意终点没糖吃)

求每个点的权值

首先想到的是先找LCA然后暴力的对权值加,显然这样效率不够好

想到了树状数组完成区间修改和单点求值,是先将[l,r]中a[l]++,然后a[r+1]--;

这样就避免了对每个数都修改;

以此类推,我们可以假定路径使x-->root-->y上的点+1,

这样每个点的权值即为其所在子树和

设lca(x,y)=z 同样的道理,我们只要对a[x]++,a[y]++,然后对a[z]--,a[fa[z]]--

因为每个点的权值即为其所在子树和,所以只有x-->y的简单路径上的点权值+1了

这样的话我们可以做一遍LCA-tarjan就可以搞出来了(当然也可以再单独扫一遍)

 1 type node=record
 2        po,next:longint;
 3        can:boolean;
 4      end;
 5  
 6 var a,q:array[0..600010] of node;
 7     fa,f,p,w,ans,g:array[0..300010] of longint;
 8     v:array[0..300010] of boolean;
 9     st,i,j,n,m,x,y,t:longint;
10  
11 function getf(x:longint):longint;
12   begin
13     if fa[x]<>x then fa[x]:=getf(fa[x]);
14     exit(fa[x]);
15   end;
16  
17 procedure addq(x,y:longint);
18   begin
19     inc(m);
20     q[m].po:=y;
21     q[m].next:=w[x];
22     w[x]:=m;
23   end;
24  
25 procedure add(x,y:longint);
26   begin
27     inc(t);
28     a[t].po:=y;
29     a[t].next:=p[x];
30     p[x]:=t;
31   end;
32  
33 procedure tarjan(x:longint);
34   var i,y,z:longint;
35   begin
36     i:=p[x];
37     v[x]:=true;
38     while i<>0 do
39     begin
40       y:=a[i].po;
41       if not v[y] then
42       begin
43         f[y]:=x;
44         tarjan(y);
45         fa[y]:=x;
46       end;
47       i:=a[i].next;
48     end;
49     i:=w[x];
50     while i<>-1 do
51     begin
52       y:=q[i].po;
53       if v[y] and not q[i].can then
54       begin
55         z:=getf(y);
56         q[i].can:=true;
57         q[i xor 1].can:=true;
58         inc(g[z]);
59         inc(g[f[z]]);
60       end;
61       i:=q[i].next;
62     end;
63     ans[x]:=ans[x]-g[x]; 
64     ans[f[x]]:=ans[f[x]]+ans[x];//做到这已经说明x的子树已经被访问完了,x的权值已经确定,直接加即可,不需要再dfs一遍
65   end;
66  
67 begin
68   m:=-1;
69   fillchar(w,sizeof(w),255);
70   readln(n);
71   read(x);
72   st:=x;
73   ans[x]:=1;
74   for i:=1 to n-1 do
75   begin
76     read(y);
77     addq(x,y);
78     addq(y,x);
79     inc(ans[y]);
80     if i<>n-1 then inc(ans[y]);
81     x:=y;
82   end;
83   for i:=1 to n-1 do
84   begin
85     readln(x,y);
86     add(x,y);
87     add(y,x);
88   end;
89   for i:=1 to n do
90     fa[i]:=i;
91  
92   tarjan(1);
93   for i:=1 to n do
94   begin
95     if i<>st then dec(ans[i]);
96     writeln(ans[i]);
97   end;
98 end.
View Code

 

posted on 2014-10-17 19:46  acphile  阅读(123)  评论(0编辑  收藏  举报