如果是树,那么一定选择树的直径的中点

套了个环?裸的想法显然是断开环,然后求所有树的直径的最小值

环套树dp的一般思路,先把环放到根,把环上点下面的子树dp出来,然后再处理环上的情况

设f[i]表示以i为根的子树向下延伸的最长链长度

我们把环上的点扩展一倍,用前缀和维护环上的边权

依次枚举断点,则对直径影响就是max(s[j]-s[i]+f[i]+f[j])

分别维护max(s[j]+f[j])和max(f[i]-s[i])

注意i≠j,所以我们还要维护一个次小值

  1 type node=record
  2        po,next,num:longint;
  3      end;
  4      link=record
  5        loc:longint;
  6        mx:int64;
  7      end;
  8 
  9 var tree:array[0..200010*4,1..2] of link;
 10     e:array[0..200010] of node;
 11     cut:array[0..200010] of boolean;
 12     a,b,p,fa:array[0..200010] of longint;
 13     v:array[0..200010] of boolean;
 14     f,s:array[0..200010] of int64;
 15     i,len,n,t,x,y,z:longint;
 16     ll,ans,lin:int64;
 17     l1,l2,tp:link;
 18 
 19 function max(a,b:int64):int64;
 20   begin
 21     if a>b then exit(a) else exit(b);
 22   end;
 23 
 24 function min(a,b:int64):int64;
 25   begin
 26     if a>b then exit(b) else exit(a);
 27   end;
 28 
 29 procedure add(x,y,z:longint);
 30   begin
 31     inc(len);
 32     e[len].po:=y;
 33     e[len].next:=p[x];
 34     e[len].num:=z;
 35     p[x]:=len;
 36   end;
 37 
 38 procedure find(x:longint);
 39   var i,y,h:longint;
 40   begin
 41     i:=p[x];
 42     while i<>-1 do
 43     begin
 44       y:=e[i].po;
 45       if not cut[i] then
 46       begin
 47         if fa[y]<>0 then
 48         begin
 49           h:=x;
 50           while h<>y do
 51           begin
 52             inc(t);
 53             a[t]:=h;
 54             b[t]:=f[h];
 55             h:=fa[h];
 56           end;
 57           inc(t);
 58           a[t]:=h;
 59           b[t]:=e[i].num;
 60           break;
 61         end
 62         else begin
 63           cut[i]:=true;
 64           cut[i xor 1]:=true;
 65           fa[y]:=x;
 66           f[y]:=e[i].num;
 67           find(y);
 68         end;
 69       end;
 70       if t<>0 then break;
 71       i:=e[i].next;
 72     end;
 73   end;
 74 
 75 procedure dfs(x:longint);
 76   var i,y:longint;
 77   begin
 78     v[x]:=true;
 79     f[x]:=0;
 80     i:=p[x];
 81     while i<>-1 do
 82     begin
 83       y:=e[i].po;
 84       if not v[y] then
 85       begin
 86         dfs(y);
 87         lin:=max(lin,f[y]+f[x]+e[i].num);
 88         f[x]:=max(f[x],f[y]+e[i].num);
 89       end;
 90       i:=e[i].next;
 91     end;
 92   end;
 93 
 94 procedure update(var c:link; a:link; b:link);
 95   begin
 96     c.mx:=a.mx;
 97     c.loc:=a.loc;
 98     if c.mx<b.mx then
 99     begin
100       c.loc:=b.loc;
101       c.mx:=b.mx;
102     end;
103   end;
104 
105 procedure build(i,l,r:longint);
106   var m:longint;
107   begin
108     if l=r then
109     begin
110       tree[i,1].mx:=f[a[l]]+s[l];
111       tree[i,1].loc:=l;
112       tree[i,2].mx:=f[a[l]]-s[l];
113       tree[i,2].loc:=l;
114     end
115     else begin
116       m:=(l+r) shr 1;
117       build(i*2,l,m);
118       build(i*2+1,m+1,r);
119       update(tree[i,1],tree[i*2,1],tree[i*2+1,1]);
120       update(tree[i,2],tree[i*2,2],tree[i*2+1,2]);
121     end;
122   end;
123 
124 function ask(i,l,r,w,x,y:longint):link;
125   var m:longint;
126       s,s1,s2:link;
127   begin
128     if (x<=l) and (y>=r) then exit(tree[i,w])
129     else begin
130       m:=(l+r) shr 1;
131       if x>m then exit(ask(i*2+1,m+1,r,w,x,y));
132       if y<=m then exit(ask(i*2,l,m,w,x,y));
133       s1:=ask(i*2,l,m,w,x,y);
134       s2:=ask(i*2+1,m+1,r,w,x,y);
135       update(s,s1,s2);
136       exit(s);
137     end;
138   end;
139 
140 begin
141   len:=-1;
142   fillchar(p,sizeof(p),255);
143   readln(n);
144   for i:=1 to n do
145   begin
146     readln(x,y,z);
147     add(x,y,z);
148     add(y,x,z);
149   end;
150   fa[1]:=-1;
151   find(1);
152   for i:=1 to t do
153   begin
154     v[a[i]]:=true;
155     a[i+t]:=a[i];
156     b[i+t]:=b[i];
157   end;
158   for i:=1 to 2*t do
159     s[i]:=s[i-1]+b[i-1];
160   for i:=1 to t do
161     dfs(a[i]);
162   build(1,1,2*t);
163   ans:=1000000000000010;
164   for i:=1 to t do
165   begin
166     l1:=ask(1,1,2*t,1,i+1,i+t);
167     l2:=ask(1,1,2*t,2,i+1,i+t);
168     if l1.loc=l2.loc then
169     begin
170       ll:=0;
171       if l1.loc>i+1 then
172       begin
173         tp:=ask(1,1,2*t,2,i+1,l1.loc-1);
174         ll:=max(ll,l1.mx+tp.mx);
175       end;
176       if l2.loc<i+t then
177       begin
178         tp:=ask(1,1,2*t,1,l2.loc+1,i+t);
179         ll:=max(ll,l2.mx+tp.mx);
180       end;
181       ans:=min(ans,max(ll,lin));
182     end
183     else ans:=min(ans,max(l1.mx+l2.mx,lin));
184   end;
185   writeln(ans/2:0:1);
186 end.
View Code

 

posted on 2015-06-30 14:45  acphile  阅读(226)  评论(0编辑  收藏  举报