树上距离——联合权值

该博客探讨了洛谷P1351问题,涉及树上两点距离为2的特殊情况。文章指出,无向图可转化为一棵树,并分析了两种距离为2的点的位置关系:距离最近公共祖先(LCA)距离均为1或存在直接的祖孙关系。解决策略是采用深度优先搜索(DFS),统计每个节点子树中除去自身外,最浅两层节点的权值和的最大值。由于计算的是无序点对,最终答案需乘以2。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目来源

洛谷P1351 联合权值

https://www.luogu.org/problemnew/show/P1351


思路

由于有n个点n-1条边 所以这个无向图可转化为一棵树

在树上距离为2的点的位置关系有两种

①距离他们的LCA距离均为1

② 其中一个点是另一个点的父节点的父节点

深搜 统计以每个节点为根节点的子树最浅(除根节点外)两层节点的权值和和最大值即可

注:这种方法求出的联合权值和是无序点对的 最后答案乘二即可


代码(C++)

#include <cstdio>
#include <bitset>
#define N 200010
using namespace std;
bitset<N> g; const long long mod=10007;
struct tree{long long m1,m2,a2;}*root;
int n,cnt,u,v,he[N],en[2*N],ne[2*N];
long long wei[N],ans1=0,ans2=0;
tree *dfs(int pos);
inline void add();
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;++i)
       scanf("%d%d",&u,&v),add();
    for(int i=1;i<=n;++i) 
       scanf("%lld",&wei[i]);
    root=dfs(1);
    printf("%lld %lld",ans1,ans2*2%mod);
    return 0;
}
tree *dfs(int pos)
{
     tree *k=new tree(),*tem;  g[pos]=1;
     k->m1=wei[pos]; k->m2=0; k->a2=0;
     for(int i=he[pos];i!=0;i=ne[i])
        if(g[en[i]]==0)
         {
               tem=dfs(en[i]);
               ans2=(ans2+tem->a2*k->m1)%mod;
               if(tem->m2*k->m1>ans1)
                    ans1=tem->m2*k->m1;
               ans2=(ans2+k->a2*tem->m1)%mod;
               if(k->m2*tem->m1>ans1)
                    ans1=k->m2*tem->m1;
               k->a2+=tem->m1;
               if(tem->m1>k->m2)
                    k->m2=tem->m1;
         }
     return k;
}
inline void add()
{
    en[++cnt]=v; ne[cnt]=he[u]; he[u]=cnt;
    en[++cnt]=u; ne[cnt]=he[v]; he[v]=cnt;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值