随笔 - 540  文章 - 0 评论 - 39 trackbacks - 0

一开始又看错题,以为同样路径上不同的休息站是算不同路径,后来发现休息站只是路径合法的条件
毫无疑问是树的分治,下面我们只要考虑计算能建休息站的路径
我们把阳看作路径权值为1,阴作为路径权值-1
点分治之后,休息站的建立只有三种情况,在根,在之前的子树路径上,在现在的子树路径上
我们先考虑休息站在根到子树的路径上,我们设d[x]表示点x到根的路径距离
能建也就是说在x到根的路径上存在一点y,d[y]=d[x],也就是当前距离之前是否出现过,打个标记即可
然后我们只要分别记录一下当前由根出发路径和为x,能否在这条路径上建休息站的路径数目就很容易统计了
注意一些地方的漏算和重复计算

  1 type node=record
  2        po,next,num:longint;
  3      end;
  4 
  5 var w,g:array[-100010..100010,0..1] of int64;
  6     s,p,f,d:array[0..100010] of longint;
  7     v:array[0..100010] of boolean;
  8     can:array[-100010..100010] of longint;
  9     e:array[0..200010] of node;
 10     l,r,root,len,i,x,tot,y,z,n:longint;
 11     ans:int64;
 12 
 13 function max(a,b:longint):longint;
 14   begin
 15     if a>b then exit(a) else exit(b);
 16   end;
 17 
 18 procedure add(x,y,z:longint);
 19   begin
 20     inc(len);
 21     e[len].po:=y;
 22     e[len].num:=z;
 23     e[len].next:=p[x];
 24     p[x]:=len;
 25   end;
 26 
 27 procedure getroot(x,fa:longint);
 28   var i,y:longint;
 29   begin
 30     i:=p[x];
 31     s[x]:=1;
 32     f[x]:=0;
 33     while i<>0 do
 34     begin
 35       y:=e[i].po;
 36       if not v[y] and (y<>fa) then
 37       begin
 38         getroot(y,x);
 39         s[x]:=s[x]+s[y];
 40         f[x]:=max(f[x],s[y]);
 41       end;
 42       i:=e[i].next;
 43     end;
 44     f[x]:=max(f[x],tot-s[x]);
 45     if f[x]<f[root] then root:=x;
 46   end;
 47 
 48 procedure dfs(x,fa:longint);
 49   var i,y:longint;
 50   begin
 51     if can[d[x]]>0 then
 52     begin
 53       inc(g[d[x],1]);
 54       ans:=ans+w[-d[x],1]+w[-d[x],0];  
 55     end
 56     else begin
 57       inc(g[d[x],0]);
 58       ans:=ans+w[-d[x],1];
 59     end;
 60     inc(can[d[x]]);
 61     r:=max(r,d[x]);
 62     if l>d[x] then l:=d[x];
 63     i:=p[x];
 64     while i<>0 do
 65     begin
 66       y:=e[i].po;
 67       if not v[y] and (y<>fa) then
 68       begin
 69         d[y]:=d[x]+e[i].num;
 70         dfs(y,x);
 71       end;
 72       i:=e[i].next;
 73     end;
 74     dec(can[d[x]]);
 75   end;
 76 
 77 procedure work(x:longint);
 78   var i,y,j:longint;
 79   begin
 80     v[x]:=true;
 81     i:=p[x];
 82     l:=0; r:=0;
 83     w[0,0]:=1;  //注意根节点可以作为终点
 84     while i<>0 do
 85     begin
 86       y:=e[i].po;
 87       if not v[y] then
 88       begin
 89         d[y]:=e[i].num;
 90         dfs(y,x);
 91         ans:=ans+(w[0,0]-1)*g[0,0];  //注意当前子树内不能建休息站且路径和为0可以和之前的子树内(不包括单独根节点)这样的路径组成合法路径(根节点是休息站),而之前的计算我们是没有算进去的
 92         for j:=l to r do
 93         begin
 94           w[j,0]:=w[j,0]+g[j,0];  //更新
 95           w[j,1]:=w[j,1]+g[j,1];
 96           g[j,0]:=0; g[j,1]:=0;
 97         end;
 98       end;
 99       i:=e[i].next;
100     end;
101     for j:=l to r do
102     begin
103       w[j,0]:=0;
104       w[j,1]:=0;
105     end;
106     i:=p[x];
107     while i<>0 do
108     begin
109       y:=e[i].po;
110       if not v[y] then
111       begin
112         root:=0;
113         tot:=s[y];
114         getroot(y,0);
115         work(root);
116       end;
117       i:=e[i].next;
118     end;
119   end;
120 
121 begin
122   readln(n);
123   for i:=1 to n-1 do
124   begin
125     readln(x,y,z);
126     if z=0 then z:=-1;
127     add(x,y,z);
128     add(y,x,z);
129   end;
130   f[0]:=n+1;
131   tot:=n;
132   len:=0;
133   getroot(1,0);
134   work(root);
135   writeln(ans);
136 end.
View Code

 

posted on 2015-03-31 16:54  acphile  阅读(...)  评论(...编辑  收藏