• bzoj3697


    一开始又看错题,以为同样路径上不同的休息站是算不同路径,后来发现休息站只是路径合法的条件
    毫无疑问是树的分治,下面我们只要考虑计算能建休息站的路径
    我们把阳看作路径权值为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
  • 相关阅读:
    Leecode刷题之旅-C语言/python-383赎金信
    Leecode刷题之旅-C语言/python-349两整数之和
    Cesium 实现粒子效果贴地(伪)
    CesiumJS 添加会动的GIF
    sleep 和 wait 区别
    Git常用命令
    java 泛型
    java 设计模式 ---- 单例模式
    java 设计模式 ---- 工场模式
    java 线程池 ---- newCachedThreadPool()
  • 原文地址:https://www.cnblogs.com/phile/p/4472961.html
Copyright © 2020-2023  润新知