洛谷P4220 [WC2018]通道

题面: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;
}

猜你喜欢

转载自www.cnblogs.com/Purple-wzy/p/12176025.html