zoukankan      html  css  js  c++  java
  • 洛谷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;
    }
    
  • 相关阅读:
    ubuntu安装mysql并使用Navicat连接
    二叉树基础知识点
    Javascript 16进制转有符号的10进制整数
    Node.js 学习笔记(二)
    API测试如何演变为应用程序开发的常规部分
    API在线文档
    API文档自动生成的方法
    快速对比API版本
    如何使用OPENAPI进行质量检查
    【分享】什么是API网关?大公司为什么都有API网关?
  • 原文地址:https://www.cnblogs.com/Purple-wzy/p/12176025.html
Copyright © 2011-2022 走看看