题面:https://www.luogu.com.cn/problem/P4220
题意:给出三棵树,求出(dis1(x,y)+dis2(x,y)+dis3(x,y))最大值。
题解:
首先,列举一下和深度、距离相关的可能用到的算法:
树剖,(dis_x)+(dis_y)-2(dis_{lca(x,y)}),虚树,点分治,边分治......
先考虑一个O((n^2)logn)的算法:对三棵树树剖,枚举(i),(j),
用(dis_x)+(dis_y)-2(dis_{lca(x,y)})求出答案。
这个算法用st表求lca可以做到O((n^2))。
考虑优化这个算法。
肯定不能直接枚举(i),(j)了,考虑采用分治算法。
先考虑淀粉质。由于一个节点有多个子树,合并子树就显得十分麻烦,
而且还不能简单地采用容斥来排除子树内的贡献。
所以考虑对第一棵树进行边分治。
确定了分界边后,第一棵树的两点间距离可以直接通过一遍DFS处理出来。
设这条边为((x,y)),我们把两边的点分别染成黑白两色,设黑为(B),白为(W),
那么当前要处理的就是(max(dis(x,i)+dis(x,y)+dis(y,j)+dis2(i,j)+dis3(i,j))),i(in){(B)},j(in){(W)}。
(dis(x,y))是个常量,可以扔到一边。再将dis2和dis3化为我们能求出的形式,即:
(max(dis(x,i)+dis(y,j)+dis2(1,i)+dis2(1,j)-2dis2(1,lca(i,j))+dis3(1,i)+dis3(1,j)-2dis3(1,lca(i,j)))。
记(val[i])= (dis1(x/y,i)+dis2(1,i)+dis3(1,i))(这里认为(dis1[x])=(dis1[y])=0),
那么要求的就是最大化(val[i]+val[j]-2dis2(1,lca(i,j))-2dis3(1,lca(i,j)))。
由于要在点集时间内解决问题,不难想到在第二棵树上建虚树跑DP。
由于可以枚举lca,现在只有(dis3(1,lca(i,j)))这一个变量了。
这里有一个lemma:设点集(S)的最远点对为(s1),(s2),(T)的最远点对为(t1),(t2),
那么(S->T)的最远点对只可能是((s1,t1)),((s1,t2)),((s2,t1)),((s2,t2))中的一个。
这就提醒我们可以分别记录子树内黑白点的最远点对。这样,就可以用DP解决问题了。
最后,具体实现上有几个小细节:
1.最好用st表求lca,避免再多一个log;
2.多开struct,开三个namespace,以防止变量重名;
3.码量巨大,出问题最好手膜一组小数据试一试。
时间复杂度:O(n(log^2)n)
代码:
#include<bits/stdc++.h>
using namespace std;
#define re register ll
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline ll
#define C(x,y) memset(x,y,sizeof(x))
#define STS system("pause")
template<class D>I read(D &res){
res=0;register D g=1;register char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')g=-1;
ch=getchar();
}
while(isdigit(ch)){
res=(res<<3)+(res<<1)+(ch^48);
ch=getchar();
}
res*=g;
}
#define T e[k].to
typedef pair<ll,ll>pil;
ll n,X,Y;ll W,ans,Cent;
ll cnt1,cnt2,q1[404000],q2[404000],clr[404000];
ll val[404000];
namespace T3{
struct E{
ll to,nt;ll w;
}e[202000];
ll head[101000],tot;
ll xu[202000],dep[202000],id[202000],lg[202000],f[202000][20];
ll dis[101000];
IN getmin(ll x,ll y){
return dep[x]<dep[y]?x:y;
}
I add(ll x,ll y,ll w){
e[++tot].to=y;e[tot].nt=head[x];head[x]=tot;e[tot].w=w;
}
I D_1(ll x,ll fa,ll depth,ll dist){
dep[x]=depth;xu[++tot]=x;id[x]=tot;dis[x]=dist;val[x]+=dis[x];
for(re k=head[x];k!=-1;k=e[k].nt){
if(T==fa)continue;
D_1(T,x,depth+1,dist+e[k].w);xu[++tot]=x;
}
}
I init(){
lg[0]=-1;
F(i,1,tot)f[i][0]=xu[i],lg[i]=lg[i>>1]+1;
F(j,1,lg[tot]){
F(i,1,tot-(1<<j)+1)f[i][j]=getmin(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
I build(){
C(head,-1);tot=-1;
F(i,1,n-1){
read(X);read(Y);read(W);
add(X,Y,W);add(Y,X,W);
}
tot=0;
D_1(1,0,1,0);init();
}
IN ques_lca(ll x,ll y){
x=id[x];y=id[y];
if(x>y)swap(x,y);
re len=lg[y-x+1];
return getmin(f[x][len],f[y-(1<<len)+1][len]);
}
IN ques_dis(ll x,ll y){return val[x]+val[y]-(dis[ques_lca(x,y)]<<1);}
};
namespace T2{
vector<pil>vec[101000];
struct E{
ll to,nt;ll w;
}e[202000];
ll head[101000],tot;
ll xu[202000],dep[202000],id[202000],lg[202000],f[202000][20],in[202000],out[202000],dfn;
ll dis[101000];
ll top,st[404000];
ll q[404000],num;
struct Dat{
ll x,y;ll dis;
Dat(){x=y=dis=0;}
Dat(const ll &_x,const ll &_y){x=_x;y=_y;dis=T3::ques_dis(x,y);}
Dat(const ll &_x,const ll &_y,const ll &_w){x=_x;y=_y;dis=_w;}
friend bool operator < (Dat a,Dat b){return a.dis<b.dis;}
friend Dat operator ^ (Dat a,Dat b){
if(!a.x)return b;if(!b.x)return a;
Dat r=max(a,b);
r=max(r,max(Dat(a.x,b.y),max(Dat(a.y,b.x),max(Dat(a.x,b.x),Dat(a.y,b.y)))));
return r;
}
}dp[202000][2];
IN getmin(ll x,ll y){
return dep[x]<dep[y]?x:y;
}
I add(ll x,ll y,ll w){
e[++tot].to=y;e[tot].nt=head[x];head[x]=tot;e[tot].w=w;
}
I D_1(ll x,ll fa,ll depth,ll dist){
dep[x]=depth;xu[++tot]=x;id[x]=tot;dis[x]=dist;val[x]+=dis[x];in[x]=++dfn;
for(re k=head[x];k!=-1;k=e[k].nt){
if(T==fa)continue;
D_1(T,x,depth+1,dist+e[k].w);xu[++tot]=x;
}
out[x]=++dfn;
}
I init(){
lg[0]=-1;
F(i,1,tot)f[i][0]=xu[i],lg[i]=lg[i>>1]+1;
F(j,1,lg[tot]){
F(i,1,tot-(1<<j)+1)f[i][j]=getmin(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
I build(){
C(head,-1);tot=-1;
F(i,1,n-1){
read(X);read(Y);read(W);
add(X,Y,W);add(Y,X,W);
}
tot=0;
D_1(1,0,1,0);init();
}
ll oc[404000],lca;
IN ques_lca(ll x,ll y){
x=id[x];y=id[y];
if(x>y)swap(x,y);
re len=lg[y-x+1];
return getmin(f[x][len],f[y-(1<<len)+1][len]);
}
IN ques(Dat a,Dat b){
if(!a.x||!b.x)return 0;
return max(max(T3::ques_dis(a.x,b.x),T3::ques_dis(a.x,b.y)),max(T3::ques_dis(a.y,b.x),T3::ques_dis(a.y,b.y)));
}
inline bool bbb(ll x,ll y){
re k1=(x<0)?out[-x]:in[x],k2=(y<0)?out[-y]:in[y];return k1<k2;
}
inline ll Max(ll x,ll y){
return x>y?x:y;
}
I solve(){
top=0;
//cout<<endl;
F(i,1,cnt1)st[++top]=q1[i];
//cout<<" ";
F(i,1,cnt2)st[++top]=q2[i];
//cout<<endl;
sort(st+1,st+1+top,bbb);
F(i,1,top)oc[st[i]]=1;
//F(i,1,n)cout<<oc[i];
//cout<<endl;
F(i,1,top){
X=st[i];W=clr[X];dp[X][W]=Dat(X,X,0),dp[X][W^1]=Dat();
}
tot=top;
//cout<<"lca:";
F(i,1,tot-1){
lca=ques_lca(st[i],st[i+1]);//cout<<lca<<" ";
if(!oc[lca])oc[lca]=1,st[++top]=lca,dp[lca][0]=dp[lca][1]=Dat();
}
//cout<<endl;
F(i,1,top)oc[st[i]]=0;
tot=top;
F(i,1,tot)st[++top]=-st[i];
sort(st+1,st+1+top,bbb);
//F(i,1,top)cout<<st[i]<<" ";
//cout<<endl;
F(i,1,top){
if(st[i]>0)q[++num]=st[i];
else {
num--;if(!num)continue;
X=q[num+1],Y=q[num];
//cout<<X<<" "<<Y<<" "<<dp[X][0].x<<" "<<dp[X][0].y<<" "<<dp[X][1].x<<" "<<dp[X][1].y<<" "<<dp[Y][0].x<<" "<<dp[Y][0].y<<" "<<dp[Y][1].x<<" "<<dp[Y][1].y<<" "<<ques(dp[X][0],dp[Y][1])+Cent-(dis[Y]<<1)<<" "<<ques(dp[X][1],dp[Y][0])+Cent-(dis[Y]<<1)<<" ";
W=Max(ques(dp[X][0],dp[Y][1]),ques(dp[X][1],dp[Y][0]))+Cent-(dis[Y]<<1);
ans=Max(ans,W);//cout<<W<<endl;
dp[Y][0]=dp[Y][0]^dp[X][0];dp[Y][1]=dp[Y][1]^dp[X][1];
}
}
}
};
namespace T1{
const ll INF=1e9+7;
vector<pil>vec[101000];
ll num[101000];
struct E{
ll to,nt;ll w;bool v;
}e[808000];
ll head[404000],tot,cnt;
ll siz[404000],V[404000],maxi;
I add(ll x,ll y,ll w){
//cout<<"!"<<x<<" "<<y<<endl;
e[++tot].to=y;e[tot].nt=head[x];head[x]=tot;e[tot].w=w;
}
I insert(ll x,pil y){
++cnt;
add(cnt,y.first,y.second);add(y.first,cnt,y.second);
add(num[x],cnt,0);add(cnt,num[x],0);num[x]=cnt;
}
I D_1(ll x,ll fa){
for(auto p:vec[x]){
if(p.first==fa)continue;
insert(x,p);
D_1(p.first,x);
}
}
I build(){
F(i,1,n-1){
read(X);read(Y);read(W);
vec[X].emplace_back(make_pair(Y,W));
vec[Y].emplace_back(make_pair(X,W));
}
C(head,-1);tot=-1;cnt=n;
F(i,1,n)num[i]=i;
D_1(1,0);
}
I D_2(ll x,ll fa){
siz[x]=1;
for(re k=head[x];k!=-1;k=e[k].nt){
if(T==fa||e[k].v)continue;
D_2(T,x);siz[x]+=siz[T];
}
}
I findroot(ll x,ll fa,ll N){
for(re k=head[x];k!=-1;k=e[k].nt){
if(T==fa||e[k].v)continue;
findroot(T,x,N);
re now=max(siz[T],N-siz[T]);
if(now<maxi)maxi=now,W=k;
}
}
I D_3(ll x,ll fa,ll depth){
V[x]=depth;if(x<=n)q1[++cnt1]=x,clr[x]=0;
for(re k=head[x];k!=-1;k=e[k].nt){
if(T==fa||e[k].v)continue;
D_3(T,x,depth+e[k].w);
}
}
I D_4(ll x,ll fa,ll depth){
V[x]=depth;if(x<=n)q2[++cnt2]=x,clr[x]=1;
for(re k=head[x];k!=-1;k=e[k].nt){
if(T==fa||e[k].v)continue;
D_4(T,x,depth+e[k].w);
}
}
I D_5(ll x,ll fa){
for(re k=head[x];k!=-1;k=e[k].nt){
if(T==fa||e[k].v)continue;
D_5(T,x);e[k].v=e[k^1].v=1;
}
}
I solve(ll x){
//cout<<"!"<<x<<" ";
D_2(x,0);if(siz[x]==1)return;
maxi=INF;
findroot(x,0,siz[x]);
ll A,B,M=W;B=e[M].to,A=e[M^1].to;
e[M].v=e[M^1].v=1;Cent=e[M].w;
cnt1=cnt2=0;
D_3(A,0,0);D_4(B,0,0);
if(!cnt1||!cnt2){
if(!cnt1&&!cnt2)return;
else if(!cnt1)D_5(A,0),solve(B);
else if(!cnt2)D_5(B,0),solve(A);
return;
}
F(i,1,cnt1)val[q1[i]]+=V[q1[i]];
F(i,1,cnt2)val[q2[i]]+=V[q2[i]];
//cout<<A<<" "<<B<<" "<<Cent<<" "<<cnt1<<" "<<cnt2<<":"<<endl;
T2::solve();
F(i,1,cnt1)val[q1[i]]-=V[q1[i]];
F(i,1,cnt2)val[q2[i]]-=V[q2[i]];
solve(A);solve(B);
}
};
int main(){
read(n);
T1::build();
T2::build();
T3::build();
//F(i,1,n)cout<<val[i]<<" ";
//cout<<endl;
T1::solve(1);
printf("%lld",ans);
return 0;
}