zoukankan      html  css  js  c++  java
  • Codeforces 1000G Two-Paths 树形动态规划 LCA

    原文链接https://www.cnblogs.com/zhouzhendong/p/9246484.html

    题目传送门 - Codeforces 1000G Two-Paths

    题意

      给定一棵有 $n(2leq nleq 3 imes 10^5)$ 个节点的树,其中节点 $i$ 有权值 $a_i$,边 $e$ 有权值 $w_e$。$(1leq a_i,w_eleq 10^9)$

      现在给出 $q(1leq qleq 4 imes 10^5)$ 组询问,每组询问给定两个数 $x,y(1leq x,yleq n)$。

      如果一条路径的起点和终点分别为 $x$ 和 $y$,而且这条路径重复经过同一条边最多 $2$ 次(点可以多次经过),那么这条路径合法。

      一条合法路径 $P$ 的价值为 $Pr(p)$。$ ext{Pr}(p) = sumlimits_{v in ext{distinct vertices in } p}{a_v} - sumlimits_{e in ext{distinct edges in } p}{k_e cdot w_e}$。

      其中 $k_e$ 为路径 $p$ 经过 $e$ 的次数。

      每次询问问所有合法路径的最大价值。

    题解

      我们来跑一下树形dp。

      求出以下值。(下面是示意图,有填色的部分表示被计算)

      其中 $dp1,dp2,f1,sum$ 都表示所取的部分的合法最大值。

      

        

      

      再描述一下上面六个量的意义:

      dp1[x]:往 $x$ 的后代节点走最多可以赚多少。

      dp2[x]:往 $x$ 的祖先走最多可以赚多少。

      f1[x]:从 $x$ 的祖先向 $x$ 走最多可以赚多少。

      sum[x]:令树根到 $x$ 父亲的链为主链,假设主链上行走没有任何消耗和获益,向主链走最多可以获益多少。

      len[x]:$x$ 到根的距离(带边权)。

      s[x]:$x$ 的深度。

      

      在回答询问 $x,y$ 的时候,首先从 $x$ 到 $y$ 的路径一定被选,其中的边一定只走一次。

      其他的我们根据之前维护的量分类讨论加加减减一下就可以了。

      详见代码。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=300005,M=N*2;
    LL read(){
    	LL x=0;
    	char ch=getchar();
    	while (!('0'<=ch&&ch<='9'))
    		ch=getchar();
    	while ('0'<=ch&&ch<='9')
    		x=x*10+ch-48,ch=getchar();
    	return x;
    }
    struct Gragh{
    	int cnt,y[M],nxt[M],fst[N];
    	LL z[M];
    	void clear(){
    		cnt=0;
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b,LL c){
    		y[++cnt]=b,z[cnt]=c,nxt[cnt]=fst[a],fst[a]=cnt;
    	}
    }g;
    int n,q,fa[N][20],depth[N],xx,yy;
    LL a[N],dp1[N],f1[N],dp2[N],sum[N],fadis[N],len[N],s[N];
    void dfs1(int x,int pre,int d,LL L){
    	fa[x][0]=pre;
    	depth[x]=d;
    	len[x]=L;
    	s[x]=s[pre]+a[x];
    	for (int i=1;i<20;i++)
    		fa[x][i]=fa[fa[x][i-1]][i-1];
    	dp1[x]=0;
    	for (int i=g.fst[x];i;i=g.nxt[i]){
    		int y=g.y[i];
    		LL z=g.z[i];
    		if (y!=pre){
    			dfs1(y,x,d+1,L+z);
    			fadis[y]=z;
    			f1[y]=max(dp1[y]+a[y]-z*2,0LL);
    			dp1[x]+=f1[y];
    		}
    	}
    }
    void dfs2(int x,int pre,LL v,LL v2){
    	dp2[x]=v;
    	sum[x]=v2;
    	for (int i=g.fst[x];i;i=g.nxt[i]){
    		int y=g.y[i];
    		LL z=g.z[i];
    		if (y!=pre){
    			LL _v=max(v+a[x]+dp1[x]-f1[y]-2*z,0LL);
    			LL _v2=max(v2+dp1[x]-f1[y],0LL);
    			dfs2(y,x,_v,_v2);
    		}
    	}
    }
    int LCA(int x,int y){
    	if (depth[x]<depth[y])
    		swap(x,y);
    	for (int i=19;i>=0;i--)
    		if (depth[x]-(1<<i)>=depth[y])
    			x=fa[x][i];
    	if (x==y)
    		return x;
    	for (int i=19;i>=0;i--)
    		if (fa[x][i]!=fa[y][i])
    			x=fa[x][i],y=fa[y][i];
    	xx=x,yy=y;
    	return fa[x][0];
    }
    int main(){
    	scanf("%d%d",&n,&q);
    	for (int i=1;i<=n;i++)
    		a[i]=read();
    	g.clear();
    	for (int i=1;i<n;i++){
    		int a=read(),b=read();
    		LL c=read();
    		g.add(a,b,c);
    		g.add(b,a,c);
    	}
    	dfs1(1,0,0,0);
    	dfs2(1,0,0,0);
    	while (q--){
    		int x,y,lca;
    		scanf("%d%d",&x,&y);
    		if (depth[x]>depth[y])
    			swap(x,y);
    		lca=LCA(x,y);
    		if (x==lca){
    			if (y==lca){
    				printf("%I64d
    ",dp1[x]+dp2[x]+a[x]);
    				continue;
    			}
    			LL ans=s[y]-s[x]+a[x];
    			ans-=len[y]-len[x];
    			ans+=sum[y]-sum[x];
    			ans+=dp2[x]+dp1[y];
    			printf("%I64d
    ",ans);
    			continue;
    		}
    		LL ans=s[x]+s[y]-s[lca]*2+a[lca];
    		ans-=len[x]+len[y]-len[lca]*2;
    		ans+=sum[x]+sum[y]-sum[xx]-sum[yy];
    		ans+=dp1[lca]-f1[xx]-f1[yy];
    		ans+=dp2[lca]+dp1[x]+dp1[y];
    		printf("%I64d
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    用Python完成一个汇率转换器
    鸿蒙如何用JS开发智能手表App
    鸿蒙如何用JS开发智能手表App
    SAP Spartacus SplitViewComponent Migration 的一个具体例子
    SAP Spartacus B2B 页面 Popover Component 的条件显示逻辑
    SAP Spartacus 升级时关于 schematics 的更新
    SAP Spartacus B2B 页面 Disable 按钮的显示原理
    SAP Spartacus B2B 页面 Disable Confirmation 对话框的显示原理
    通过 Feature Level 动态控制 SAP Spartacus 的页面显示
    SAP Commerce Cloud Build Manifest Components
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/CF1000G.html
Copyright © 2011-2022 走看看