[loj2339]通道


类似于

对第一棵树边分治,对第二棵树建立虚树,并根据直径合并的性质来处理第三棵树(另外在第三棵树中计算距离需要使用dfs序+ST表做到$o(1)$优化)

总复杂度为$o(n\log^{2}n)$,可以通过

  1 #include
  2 using namespace std;
  3 #define N 100005
  4 #define ll long long
  5 #define pii pair
  6 #define vi vector
  7 #define fi first
  8 #define se second
  9 struct Edge{
 10     int nex,to;
 11     ll len; 
 12 };
 13 int n;
 14 ll ans,val[N];
 15 ll calc(vi x,vi y);
 16 ll dis3(int x,int y);
 17 namespace T1{
 18     int m,E,rt,x,y,head[N<<1],sz[N<<1],vis[N<<1];
 19     ll z,dep[N<<1];
 20     vi v,vx,vy;
 21     vectorint,ll> >e[N<<1];
 22     Edge edge[N<<2];
 23     void add(int x,int y,ll z){
 24         edge[E]=Edge{head[x],y,z};
 25         head[x]=E++;
 26     }
 27     void dfs(int k,int fa,ll s){
 28         dep[k]=s;
 29         for(int i=head[k];i!=-1;i=edge[i].nex)
 30             if (edge[i].to!=fa)dfs(edge[i].to,k,s+edge[i].len);
 31         v.clear();
 32         for(int i=head[k];i!=-1;i=edge[i].nex)
 33             if (edge[i].to!=fa)v.push_back(edge[i].to);
 34         int lst=k;
 35         for(int i=0;i+2){
 36             e[lst].push_back(make_pair(v[i],dep[v[i]]-dep[k]));
 37             e[lst].push_back(make_pair(++m,0));
 38             lst=m;
 39         }
 40         if (v.size()){
 41             e[lst].push_back(make_pair(v.back(),dep[v.back()]-dep[k]));
 42             v.pop_back();
 43             if (v.size())e[lst].push_back(make_pair(v.back(),dep[v.back()]-dep[k]));
 44         }
 45     }
 46     void build(){
 47         m=n;
 48         memset(head,-1,sizeof(head));
 49         for(int i=1;i){
 50             scanf("%d%d%lld",&x,&y,&z);
 51             add(x,y,z),add(y,x,z);
 52         }
 53         dfs(1,0,0);
 54         E=0;
 55         memset(head,-1,sizeof(head));
 56         for(int i=1;i<=m;i++)assert(e[i].size()<=2); 
 57         for(int i=1;i<=m;i++)
 58             for(int j=0;j){
 59                 add(i,e[i][j].fi,e[i][j].se);
 60                 add(e[i][j].fi,i,e[i][j].se);
 61             }
 62     }
 63     void get_sz(int k,int fa){
 64         sz[k]=1;
 65         for(int i=head[k];i!=-1;i=edge[i].nex)
 66             if ((!vis[i>>1])&&(edge[i].to!=fa)){
 67                 get_sz(edge[i].to,k);
 68                 sz[k]+=sz[edge[i].to];
 69             } 
 70     }
 71     void get_rt(int k,int fa,int s){
 72         for(int i=head[k];i!=-1;i=edge[i].nex)
 73             if ((!vis[i>>1])&&(edge[i].to!=fa)){
 74                 get_rt(edge[i].to,k,s);
 75                 if ((s<=3*sz[edge[i].to]+1)&&(3*sz[edge[i].to]<=(s+1<<1)))rt=(i>>1);
 76             }
 77     }
 78     void get_v(vi &v,int k,int fa,ll s){
 79         if (k<=n){
 80             val[k]=s;
 81             v.push_back(k);
 82         }
 83         for(int i=head[k];i!=-1;i=edge[i].nex)
 84             if ((!vis[i>>1])&&(edge[i].to!=fa))get_v(v,edge[i].to,k,s+edge[i].len);
 85     }
 86     void divide(int k){
 87         get_sz(k,0);
 88         if (sz[k]==1)return;
 89         get_rt(k,0,sz[k]);
 90         k=rt,vis[k]=1;
 91         vx.clear(),vy.clear();
 92         get_v(vx,edge[k<<1].to,0,0);
 93         get_v(vy,edge[(k<<1)|1].to,0,0);
 94         ans=max(ans,calc(vx,vy)+edge[k<<1].len);
 95         divide(edge[k<<1].to);
 96         divide(edge[(k<<1)|1].to);
 97     }
 98 };
 99 namespace T2{
100     int E,x,y,head[N],dfn[N],sh[N],f[N][20],st[N];
101     ll z,ans,dep[N];
102     pii mx[N][2];
103     vi v0,v,e[N];
104     Edge edge[N<<1];
105     bool cmp(int x,int y){
106         return dfn[x]<dfn[y];
107     }
108     void add(int x,int y,ll z){
109         edge[E]=Edge{head[x],y,z};
110         head[x]=E++;
111     }
112     int lca(int x,int y){
113         if (sh[x]<sh[y])swap(x,y);
114         for(int i=19;i>=0;i--)
115             if (sh[f[x][i]]>=sh[y])x=f[x][i];
116         if (x==y)return x;
117         for(int i=19;i>=0;i--)
118             if (f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
119         return f[x][0];
120     }
121     void dfs(int k,int fa,int s1,ll s2){
122         dfn[k]=++dfn[0],sh[k]=s1,dep[k]=s2;
123         f[k][0]=fa;
124         for(int i=1;i<20;i++)f[k][i]=f[f[k][i-1]][i-1];
125         for(int i=head[k];i!=-1;i=edge[i].nex)
126             if (edge[i].to!=fa)dfs(edge[i].to,k,s1+1,s2+edge[i].len);
127     }
128     void build(){
129         memset(head,-1,sizeof(head));
130         for(int i=1;i){
131             scanf("%d%d%lld",&x,&y,&z);
132             add(x,y,z),add(y,x,z);
133         }
134         dfs(1,1,0,0);
135     }
136     void build(vi v0){
137         bool flag=0;
138         for(int i=0;i)
139             if (v0[i]==1)flag=1;
140         if (!flag){
141             v0.push_back(1);
142             v.push_back(1);
143         }
144         sort(v0.begin(),v0.end(),cmp);
145         st[0]=st[1]=1;
146         for(int i=1;i){
147             int k=lca(v0[i],st[st[0]]);
148             while ((st[0]>1)&&(dfn[st[st[0]-1]]>=dfn[k])){
149                 e[st[st[0]-1]].push_back(st[st[0]]);
150                 st[0]--;
151             }
152             if (k!=st[st[0]]){
153                 v.push_back(k);
154                 e[k].push_back(st[st[0]]);
155                 st[st[0]]=k;
156             }
157             st[++st[0]]=v0[i];
158         }
159         while (st[0]>1){
160             e[st[st[0]-1]].push_back(st[st[0]]);
161             st[0]--;
162         }
163     }
164     ll merge_ans(pii x,pii y){
165         return max(max(dis3(x.fi,y.fi),dis3(x.fi,y.se)),max(dis3(x.se,y.fi),dis3(x.se,y.se)));
166     }
167     pii merge(pii x,pii y){
168         pii ans=x;
169         if (dis3(y.fi,y.se)>dis3(ans.fi,ans.se))ans=y;
170         if (dis3(x.fi,y.fi)>dis3(ans.fi,ans.se))ans=make_pair(x.fi,y.fi);
171         if (dis3(x.fi,y.se)>dis3(ans.fi,ans.se))ans=make_pair(x.fi,y.se);
172         if (dis3(x.se,y.fi)>dis3(ans.fi,ans.se))ans=make_pair(x.se,y.fi);
173         if (dis3(x.se,y.se)>dis3(ans.fi,ans.se))ans=make_pair(x.se,y.se);
174         return ans;
175     }
176     void dfs(int k){
177         for(int i=0;i){
178             dfs(e[k][i]);
179             ans=max(ans,merge_ans(mx[k][0],mx[e[k][i]][1])-(dep[k]<<1));
180             ans=max(ans,merge_ans(mx[k][1],mx[e[k][i]][0])-(dep[k]<<1));
181             mx[k][0]=merge(mx[k][0],mx[e[k][i]][0]);
182             mx[k][1]=merge(mx[k][1],mx[e[k][i]][1]); 
183         }
184     }
185     ll calc(vi vx,vi vy){
186         ans=0,v0.clear();
187         for(int i=0;i)v0.push_back(vx[i]);
188         for(int i=0;i)v0.push_back(vy[i]);
189         for(int i=0;idep[v0[i]];
190         v=v0,build(v0);
191         for(int i=0;i0]=mx[v[i]][1]=make_pair(-1,-1);
192         for(int i=0;i0]=make_pair(vx[i],vx[i]);
193         for(int i=0;i1]=make_pair(vy[i],vy[i]);
194         dfs(1);
195         for(int i=0;i)e[v[i]].clear();
196         return ans;
197     }
198 };
199 namespace T3{
200     int m,E,x,y,lg[N<<1],head[N],pos[N];
201     ll z,ans,dep[N<<1],f[N<<1][20];
202     Edge edge[N<<1];
203     void add(int x,int y,ll z){
204         edge[E]=Edge{head[x],y,z};
205         head[x]=E++;
206     }
207     ll get_min(int x,int y){
208         int m=lg[y-x+1];
209         return min(f[x][m],f[y-(1<1][m]);
210     }
211     ll dis(int x,int y){
212         x=pos[x],y=pos[y];
213         if (x>y)swap(x,y);
214         return dep[x]+dep[y]-(get_min(x,y)<<1);
215     }
216     void dfs(int k,int fa,ll s){
217         dep[++m]=s,pos[k]=m;
218         for(int i=head[k];i!=-1;i=edge[i].nex)
219             if (edge[i].to!=fa){
220                 dfs(edge[i].to,k,s+edge[i].len);
221                 dep[++m]=s;
222             }
223     }
224     void build(){
225         memset(head,-1,sizeof(head));
226         for(int i=1;i){
227             scanf("%d%d%lld",&x,&y,&z);
228             add(x,y,z),add(y,x,z);
229         }
230         dfs(1,0,0);
231         lg[0]=-1;
232         for(int i=1;i<=m;i++)lg[i]=lg[i>>1]+1;
233         for(int i=m;i;i--){
234             f[i][0]=dep[i];
235             for(int j=1;j<20;j++)f[i][j]=min(f[i][j-1],f[min(i+(1<1),m)][j-1]);
236         }
237     }
238 };
239 ll calc(vi vx,vi vy){
240     return T2::calc(vx,vy);
241 }
242 ll dis3(int x,int y){
243     if ((x<0)||(y<0))return -1e18;
244     return val[x]+val[y]+T3::dis(x,y); 
245 }
246 int main(){
247     scanf("%d",&n);
248     T1::build();
249     T2::build();
250     T3::build();
251     T1::divide(1);
252     printf("%lld\n",ans);
253     return 0;
254 }