bzoj1787

首先考虑两个点的最优集合点,必然是在这两点间最短路径上

三个点的最优集合点,不难猜测,是在两两之间的LCA上取,

那到底取哪个呢?有一个偷懒的思维方法

由于最后的最优集合点唯一,如果有两个LCA相等,则一定是另外一个

当然事实也是这样

选定了集合点之后,设选的是a,b的LCA,ab到集合点的距离在LCA中可以求出,

但c点到集合点的距离呢?还要再做一次LCA……

所以比较烦

  1 type link=^node;
  2      node=record
  3        po:longint;
  4        next:link;
  5      end;
  6      point=^ask;
  7      ask=record
  8        po,num:longint;
  9        next:point;
 10      end;
 11 
 12 var a:array[0..2000010] of point;
 13     w:array[0..500010] of link;
 14     al,b,d,fa,loc:array[0..500010] of longint;
 15     ans:array[0..2000010] of longint;
 16     c:array[0..500010,0..3] of longint;
 17     v:array[0..500010] of boolean;
 18     n,m,i,j,x,y,z:longint;
 19 
 20 procedure add(x,y:longint);
 21   var p:link;
 22   begin
 23     new(p);
 24     p^.po:=y;
 25     p^.next:=w[x];
 26     w[x]:=p;
 27   end;
 28 
 29 procedure que(x,y,p:longint);
 30   var q:point;
 31   begin
 32     new(q);
 33     q^.num:=p;
 34     q^.po:=y;
 35     q^.next:=a[x];
 36     a[x]:=q;
 37   end;
 38 
 39 function getf(x:longint):longint;
 40   begin
 41     if fa[x]<>x then fa[x]:=getf(fa[x]);
 42     exit(fa[x]);
 43   end;
 44 
 45 procedure lca(x:longint);
 46   var p:link;
 47       q,pre:point;
 48       y,e:longint;
 49   begin
 50     p:=w[x];
 51     v[x]:=true;
 52     while p<>nil do
 53     begin
 54       y:=p^.po;
 55       if not v[y] then
 56       begin
 57         d[y]:=d[x]+1;
 58         lca(y);
 59         fa[y]:=x;
 60       end;
 61       p:=p^.next;
 62     end;
 63     q:=a[x];
 64     while q<>nil do
 65     begin
 66       y:=q^.po;
 67       if v[y] and (ans[q^.num]=0) then ans[q^.num]:=getf(y);
 68       pre:=q;
 69       q:=q^.next;
 70       dispose(pre);
 71     end;
 72   end;
 73 
 74 function get(i:longint):longint;
 75   begin
 76     if al[i]=1 then
 77       exit(d[c[i,2]]+d[c[i,3]]-2*d[loc[i]]+d[loc[i]]+d[c[i,1]]-2*d[ans[i]])
 78     else if al[i]=2 then
 79       exit(d[c[i,1]]+d[c[i,3]]-2*d[loc[i]]+d[loc[i]]+d[c[i,2]]-2*d[ans[i]])
 80     else exit(d[c[i,1]]+d[c[i,2]]-2*d[loc[i]]+d[loc[i]]+d[c[i,3]]-2*d[ans[i]]);
 81   end;
 82 
 83 begin
 84   readln(n,m);
 85   for i:=1 to n-1 do
 86   begin
 87     readln(x,y);
 88     add(x,y);
 89     add(y,x);
 90   end;
 91   for i:=1 to n do
 92     fa[i]:=i;
 93   for i:=1 to m do
 94   begin
 95     readln(x,y,z);
 96     c[i,1]:=x;
 97     c[i,2]:=y;
 98     c[i,3]:=z;
 99     que(x,y,i);
100     que(y,x,i);
101     que(y,z,i+m);
102     que(z,y,i+m);
103     que(x,z,i+2*m);
104     que(z,x,i+2*m);
105   end;
106   d[1]:=0;
107   lca(1);
108   for i:=1 to n do
109   begin
110     fa[i]:=i;
111     a[i]:=nil;
112     v[i]:=false;
113     d[i]:=0;
114   end;
115   for i:=1 to m do
116   begin
117     if ans[i]=ans[i+m] then
118     begin
119       loc[i]:=ans[i+2*m];
120       al[i]:=2;
121       que(loc[i],c[i,2],i);
122       que(c[i,2],loc[i],i);
123     end
124     else if ans[i]=ans[i+2*m] then
125     begin
126       loc[i]:=ans[i+m];
127       al[i]:=1;
128       que(loc[i],c[i,1],i);
129       que(c[i,1],loc[i],i);
130     end
131     else begin
132       loc[i]:=ans[i];
133       al[i]:=3;
134       que(loc[i],c[i,3],i);
135       que(c[i,3],loc[i],i);
136     end;
137     ans[i]:=0;
138   end;
139   lca(1);
140   for i:=1 to m do
141     writeln(loc[i],' ',get(i));
142 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473161.html