[loj2339]通道
类似于[loj2553]
对第一棵树边分治,对第二棵树建立虚树,并根据直径合并的性质来处理第三棵树(另外在第三棵树中计算距离需要使用dfs序+ST表做到$o(1)$优化)
总复杂度为$o(n\log^{2}n)$,可以通过

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 100005
4 #define ll long long
5 #define pii pair<int,int>
6 #define vi vector<int>
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 vector<pair<int,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<v.size();i++){
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<n;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<e[i].size();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<n;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<v0.size();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<v0.size();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<e[k].size();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<vx.size();i++)v0.push_back(vx[i]);
188 for(int i=0;i<vy.size();i++)v0.push_back(vy[i]);
189 for(int i=0;i<v0.size();i++)val[v0[i]]+=dep[v0[i]];
190 v=v0,build(v0);
191 for(int i=0;i<v.size();i++)mx[v[i]][0]=mx[v[i]][1]=make_pair(-1,-1);
192 for(int i=0;i<vx.size();i++)mx[vx[i]][0]=make_pair(vx[i],vx[i]);
193 for(int i=0;i<vy.size();i++)mx[vy[i]][1]=make_pair(vy[i],vy[i]);
194 dfs(1);
195 for(int i=0;i<v.size();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<<m)+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<n;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<<j-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 }
[loj2339]通道的更多相关文章
- 【loj2339】【WC2018】通道
题目 三棵带边权的树,求 \[ dis1(u,v) + dis2(u,v) + dis3(u,v) \] 的最大值 \(1 \le n \le 10^5\) 题解 对\(T_1\)做边分治,把分治边的 ...
- Paypal开发中遇到请求被中止: 未能创建 SSL/TLS 安全通道及解决方案
最近在基于ASP.NET上开发了Paypal支付平台,在ASP.NET开发的过程中没有遇到这个问题,但是引用到MVC开发模式中的时候就出现了"未能创建 SSL/TLS 安全通道及解决方案&q ...
- JAVA NIO Socket通道
DatagramChannel和SocketChannel都实现定义读写功能,ServerSocketChannel不实现,只负责监听传入的连接,并建立新的SocketChannel,本身不传输数 ...
- 学习 opencv---(4) 分离颜色通道 && 多通道混合
上篇文章中我们讲到了使用addWeighted函数进行图像混合操作,以及将ROI和addWeighted函数结合起来使用,对指定区域进行图像混合操作. 而为了更好地观察一些图像材料的特征,有时需要对R ...
- 关于QImage提取单色通道方法(vector)
转载请标明处: 作者:微微苏荷 本文地址:关于QImage提取单色通道方法(vector) 近日,用QT和mxnet结合做一个图像识别的demo.遇到需要把图片从QImage转为vector单色分离的 ...
- 基于暗通道优先算法的去雾应用(Matlab/C++)
基于暗通道优先的单幅图像去雾算法(Matlab/C++) 算法原理: 参见论文:Single Image Haze Removal Using Dark Channel Pri ...
- Java NIO4:Socket通道
Socket通道 上文讲述了通道.文件通道,这篇文章来讲述一下Socket通道,Socket通道与文件通道有着不一样的特征,分三点说: 1.NIO的Socket通道类可以运行于非阻塞模式并且是可选择的 ...
- Java NIO3:通道和文件通道
通道是什么 通道式(Channel)是java.nio的第二个主要创新.通道既不是一个扩展也不是一项增强,而是全新的.极好的Java I/O示例,提供与I/O服务的直接连接.Channel用于在字节缓 ...
- IO通道
本文原创,转载需标明原处. 通道,主要负责传输数据,相当于流,但流只能是输入或输出类型中的其一,而通道则可以兼并二者. 通道的基类是:Channel boolean isOpen() void clo ...
随机推荐
- Snipaste屏幕截图的使用
什么是Snipaste Snipaste是一款屏幕截图软件 类似于微信的截图 Snipaste使用步骤 百度搜索Snipaste 如图 点击 根据自己电脑系统选择安装 下载完成后 解压到当前文件夹 点 ...
- RobotFramework+Selenium如何提高脚本稳定性
通过RF来跑selenium的脚本,正常运行一遍都没有问题,但如果要多次运行,提高脚本的稳定性,那么应该如何做呢? 当然有时候最简单最简单的方法就是直接通过sleep来等待,虽然简单粗暴,但会带来 ...
- Java基础之(十三):类与对象
初识面向对象 面向对象 & 面向过程 面向过程思想 步骤清晰简单,第一步做什么,第二步做什么..... 面向过程适合处理一些较为简单的问题 面向对象思想 物以类聚,分类的思维模式,思考问题 ...
- zabbix和prometheus的优缺点对比
使用Prometheus(https://github.com/prometheus)原生的k8s服务发现驱动,采集容器化信息:通过微服务参数配置,暴露运行状态信息提供给prometheus,实现微服 ...
- LinkedList-常用方法以及双向链表的理解
链表 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的. 链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两 ...
- 【c++ Prime 学习笔记】第2章 变量和基本类型
2.1 基本内置类型 基本数据类型包含了算术类型(arithmetic type)和空类型(void) 算数类型,包含了字符.整型数.布尔值和浮点数 空类型,不对应具体的值 2.1.1 算术类型 算术 ...
- JDBC:(java database Connection) java数据库连接。
JDBC 指 Java 数据库连接,是一种标准Java应用编程接口( JAVA API),用来连接 Java 编程语言和广泛的数据库. JDBC连接步骤: 1.先导入jar包,把jar放入到工程下并 ...
- Linux argc,argv详解
来源:微信公众号「编程学习基地」 @ 目录 argc,argv是什么 如何解析程序参数 "选项"是什么? "选项字符串"是什么 解析参数 argc,argv是什 ...
- [对对子队]会议记录5.18(Scrum Meeting5)
今天已完成的工作 何瑞 工作内容:搭建第8关 相关issue:搭建关卡7.8.9 相关签入:feat:初步搭建了Lv8 吴昭邦 工作内容:搭建第8关 相关issue:搭建关卡7.8 ...
- 【二食堂】Beta - Scrum Meeting 2
Scrum Meeting 2 例会时间:5.14 18:30~18:50 进度情况 组员 当前进度 今日任务 李健 1. 还在进行摸索,目前做出了一个demo可以进行简单的划词 issue 1. 继 ...