[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 ...
随机推荐
- mysql从零开始之MySQL 创建数据库
MySQL 创建数据库 我们可以在登陆 MySQL 服务后,使用 create 命令创建数据库,语法如下: CREATE DATABASE 数据库名; 以下命令简单的演示了创建数据库的过程,数据名为 ...
- WPF进阶技巧和实战08-依赖属性与绑定02
将元素绑定在一起 数据绑定最简单的形式是:源对象是WPF元素而且源属性是依赖项属性.依赖项属性内置了更改通知支持,当源对象中改变依赖项属性时,会立即更新目标对象的绑定属性. 元素绑定到元素也是经常使用 ...
- Dapr + .NET Core实战(十四)虚拟机集群部署 mDNS + Consul
前面我们说了在单机模式下和K8S集群下的Dapr实战,这次我们来看看如何在不使用K8S的情况下,在一个传统的虚拟机集群里来部署Dapr. 1.环境准备 我们准备两台centos7虚拟机 Dapr1:1 ...
- mysql select语句查询流程是怎么样的
select查询流程是怎么样的 mysql select查询的数据是查询内存里面,如果没有查询的数据没有在内存,就需要mysql的innodb引擎读取磁盘,将数据加载的内存后在读取.这就体现了,mys ...
- 计算机网络:HTTP
计算机网络基础:HTTP 先验知识 HTTP和其他协议的关系 通过下图,了解IP协议,TCP协议,DNS服务在使用HTTP协议通信过程中各自发挥的作用: 服务器处理流程 接受客户端连接 ------& ...
- UltraSoft - Beta - Scrum Meeting 5
Date: May 21st, 2020. Scrum 情况汇报 进度情况 组员 负责 今日进度 q2l PM.后端 修复了课程通知链接的bug Liuzh 前端 暂无 Kkkk 前端 增加消息中心板 ...
- .net,C#,Vb,F#,Asp,Asp.net区别以及作用和方向
.net是平台,其他都是运行在其.NET FrameWork环境下的 C#,Vb都是语言运行在.net 平台下 Asp,Asp.net 都是用来写Web网页的,但是Asp和Asp.net有区别 Asp ...
- spring cloud config的使用
在传统的应用中,我们的配置文件都是放在项目中,这个影响不大.但是在一个微服务架构的系统中,我们的微服务可能存在几十上百个,并且每个小的微服务可能又部署在多台机器上,那么这个时候如果我们的配置文件在都放 ...
- python redis自带门神 lock 方法
redis 支持的数据结构比较丰富,自制一个锁也很方便,所以极少提到其原生锁的方法.但是在单机版redis的使用时,自带锁的使用还是非常方便的.自己有车还打啥滴滴顺风车是吧,本篇主要介绍redis-p ...
- 单片机stm32 USART串口实际应用解析
stm32作为现在嵌入式物联网单片机行业中经常要用多的技术,相信大家都有所接触,今天这篇就给大家详细的分析下有关于stm32的出口,还不是很清楚的朋友要注意看看了哦,在最后还会为大家分享有些关于stm ...