【树论】两棵树
WC2018 T1 简化版 by OBlack.
有两棵有 n 个节点的树,分别为 A,B,树上每条边都有一个权值 v_i
令 disA(x,y) 和 disB(x,y) 分别表示 x 节点与 y 节点在树 A,B 上的距离
请你找出一个点对 (x,y) 使得 disA(x,y)+disB(x,y) 取得最大值,注意 x!=y
输入格式
第一行,一个整数 n
接下来 n-1 行,每行三个整数 x_i,y_i,v_i ,表示 A 上的一条边
接下来 n-1 行,每行三个整数 x_i,y_i,v_i ,表示 B 上的一条边
输出格式
输出一个整数 Ans ,表示最大值
样例输入
5
4 5 6
4 1 2
5 2 1
4 3 0
4 1 9
4 2 0
1 5 0
5 3 7
样例输出
23
提示
对于 30% 的数据, n<=2000,v_i<=10^6
对于所有数据, n<=10^5, v_i<=10^12
本题为 WC2018 T1 (NKOJ 5004) 简化版
题解
我们将dis1(x,y)+dis2(x,y)变一下形 --> dep1[x] + dep1[y] - 2*dep1[lca1(x,y)] + dep2[x] + dep2[y] - 2*dep2[lca2(x,y)] 我们发现对于任何x,他的dep1[x]和dep2[x]在式子中总是成对出现的。那么我们将他们合并在一起考虑-->方法是将第二棵树中的x,每个对应在其下连一条dep1[x]的边,并设置新节点为x'。同时我们在第一棵树中枚举lca,那么问题就变成了--->对于第一棵树的lca,对于他的分别两个子树合并的时候的两个点集,分别对应在第二棵树中的两个离散的点集,在其中找一条最长的路径。也就是比如对于x的son1对应一些点集,son2对应一些点集,(因为在这两个点集中各选一个保证他们在第一棵树树上的lca一定为x)然后两个中各自挑选一个的最长路径。 其实对于这样两个离散点集中,分别各自对应着两个直径。容易证明。对于两个离散点集,他们之间的最长路径的端点一定是分别在他们的直径4个点上。同时,也可以证明,对于两个离散点集他们合并之后的那个点集的直径的端点,也一定是两个离散点集的四个端点之二。 这样我们只需要变换一下第二颗树,然后在第一棵树上dfs合并子树,在第二颗树上查询最长路径更新答案(LCA次数比较多,考虑O(1)LCA),就可以了。。/*
在第一棵树上枚举lca,由于式子
disa(x,y) + disb(x,y) == dep1x + dep1y -2*lca1 + dep2x + dep2y - 2*lca2
可以在第二棵树上外挂一个节点,那么就是对于第二棵树上的一个点集内的求点集了
然后直接直径合并就可以了
*/
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define pr pair<int,int>
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int maxn = 1000005;
const int maxm = 2000005;
ll len1[maxm];
int la1[maxn],nt1[maxm],en1[maxm],owo1;
void addedge1(int a,int b,ll c) {
en1[++owo1] = b; nt1[owo1] = la1[a];
la1[a] = owo1; len1[owo1] = c;
}
ll len2[maxm];
int la2[maxn],nt2[maxm],en2[maxm],owo2;
void addedge2(int a,int b,ll c) {
en2[++owo2] = b; nt2[owo2] = la2[a];
la2[a] = owo2; len2[owo2] = c;
}
ll dep1[maxn],dep2[maxn];
int n;
int ST[23][maxn*2],lac[maxn],oula;
char buf[1<<20],*p1,*p2;
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
//#define GC getchar()
inline ll R()
{
char t=GC;
ll x=0;
while(!isdigit(t)) t=GC;
while(isdigit(t)) x=x*10+t-48,t=GC;
return x;
}
void dfs1(int x,int ba) {
for(int it=la1[x];it;it=nt1[it]) {
int y = en1[it];
if(y==ba) continue;
dep1[y] = dep1[x] + len1[it];
dfs1(y,x);
}
}
int logg[maxn*2];
int S;
void dfs2(int x,int ba) {
ST[0][++oula] = x;
for(int it=la2[x];it;it=nt2[it]) {
int y = en2[it];
if(y==ba) continue;
dep2[y] = dep2[x] + len2[it];
dfs2(y,x);
ST[0][++oula] = x;
}
lac[x] = oula;
}
ll ans = -1e18;
int getlca(int x,int y) {
x = lac[x]; y = lac[y];
if(x>y) swap(x,y);
int k = logg[y-x+1];
return dep2[ST[k][x]] < dep2[ST[k][y-(1<<k)+1]] ? ST[k][x] : ST[k][y-(1<<k)+1];
}
ll getcd(int x,int y) {
int lcc = getlca(x,y);
return dep2[x] + dep2[y] - 2*dep2[lcc];
}
pr merge(pr a,pr b) {
pr now = a; ll ccd = getcd(a.fi,a.se);
ll tmp = getcd(b.fi,b.se);
if(tmp>ccd) {
now = b; ccd = tmp;
}
tmp = getcd(a.fi,b.fi);
if(tmp>ccd) {
now = pr(a.fi,b.fi); ccd = tmp;
}
tmp = getcd(a.fi,b.se);
if(tmp>ccd) {
now = pr(a.fi,b.se); ccd = tmp;
}
tmp = getcd(a.se,b.fi);
if(tmp>ccd) {
now = pr(a.se,b.fi); ccd = tmp;
}
tmp = getcd(a.se,b.se);
if(tmp>ccd) {
now = pr(a.se,b.se); ccd = tmp;
}
return now;
}
pr dfs3(int x,int ba) {
pr zj = pr(x+n,x+n);
for(int it=la1[x];it;it=nt1[it]) {
int y = en1[it];
if(y==ba) continue;
pr tmp = dfs3(y,x);
ans = max(getcd(tmp.fi,zj.fi)-2*dep1[x],ans);
ans = max(getcd(tmp.fi,zj.se)-2*dep1[x],ans);
ans = max(getcd(tmp.se,zj.fi)-2*dep1[x],ans);
ans = max(getcd(tmp.se,zj.se)-2*dep1[x],ans);
zj = merge(zj,tmp);
}
return zj;
}
main() {
// freopen("aha.in","r",stdin);
// freopen("aha.out","w",stdout);
n=R();
for(int i=1;i<n;i++) {
int x,y;ll z; x=R(); y=R(); z=R();
addedge1(x,y,z); addedge1(y,x,z);
}
dfs1(1,0);
for(int i=1;i<=n;i++) {
addedge2(i,i+n,dep1[i]);
addedge2(i+n,i,dep1[i]);
}
for(int i=1;i<n;i++) {
int x,y;ll z; x=R();y=R();z=R();
addedge2(x,y,z); addedge2(y,x,z);
}
dfs2(1,0);
logg[0]=logg[1]=0;
for(int i=2;i<=oula;i++) logg[i] = logg[i>>1] + 1;
for(int s=1;s<=logg[oula];s++) {
for(int i=1;i+(1<<s)-1<=oula;i++) {
ST[s][i] = dep2[ST[s-1][i]] < dep2[ST[s-1][i+(1<<(s-1))]] ? ST[s-1][i] : ST[s-1][i+(1<<(s-1))];
}
}
dfs3(1,0);
printf("%lld",ans);
}

浙公网安备 33010602011771号