P1351 联合权值(树形dp)

P1351 联合权值

想刷道水题还交了3次.....丢人

(1.没想到有两个点都是儿子的状况 2.到处乱%(大雾))

先dfs一遍处理出父亲$fa[x]$

蓝后再一遍dfs,搞搞就出来了。

#include<iostream>
#include<cstdio>
#include<cstring>
#define re register
using namespace std;
const int p=10007;
int max(int &a,int &b){return a>b?a:b;}
#define N 200002
int n,fa[N],val[N],f1[N],f2[N];
int cnt,hd[N],nxt[N<<1],ed[N],poi[N<<1];
void adde(int x,int y){
    nxt[ed[x]]=++cnt; hd[x]=hd[x]?hd[x]:cnt;
    ed[x]=cnt; poi[cnt]=y;
}
void dfs1(int x,int ffa){//处理fa数组
    fa[x]=ffa;
    for(int i=hd[x];i;i=nxt[i])
        if(poi[i]!=ffa)
            dfs1(poi[i],x);
}
void dfs2(int x){
    int mxd=0,tot=0;
    for(int i=hd[x];i;i=nxt[i]){
        int to=poi[i];
        if(to==fa[x]) continue;
        f1[x]=max(f1[x],val[to]*mxd);
        f2[x]=1ll*(f2[x]+val[to]*tot)%p;
        mxd=max(mxd,val[to]);//以上为构成联合权值的2个点都是儿子的情况
        tot=(tot+val[to])%p;
        dfs2(to);
        f1[x]=max(f1[x],f1[to]);
        f2[x]=1ll*(f2[x]+f2[to])%p;
    }
    int g=fa[fa[x]],v=val[x]*val[g];//点x和x的爷爷构成联合权值
    f1[g]=max(f1[g],v);
    f2[g]=1ll*(f2[g]+v)%p;
}
int main(){
    scanf("%d",&n); int q1,q2;
    for(int i=1;i<n;++i){
        scanf("%d%d",&q1,&q2);
        adde(q1,q2); adde(q2,q1);
    }
    for(int i=1;i<=n;++i) scanf("%d",&val[i]);
    dfs1(1,0); dfs2(1); f2[1]=1ll*f2[1]*2%p;//记得*2
    printf("%d %d",f1[1],f2[1]);
    return 0;
}

原文地址:https://www.cnblogs.com/kafuuchino/p/9807375.html

时间: 2024-10-08 00:00:49

P1351 联合权值(树形dp)的相关文章

P1351 联合权值

P1351 联合权值 题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离.对于图G 上的点对( u, v) ,若它们的距离为2 ,则它们之间会产生Wu×Wv 的联合权值. 请问图G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少? 输入输出格式 输入格式: 输入文件名为link .in. 第一行包含1 个整数n . 接

洛谷 P1351 联合权值(NOIp2014D1T2)

题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离.对于图G 上的点对( u, v) ,若它们的距离为2 ,则它们之间会产生Wu×Wv 的联合权值. 请问图G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少? 输入输出格式 输入格式: 输入文件名为link .in. 第一行包含1 个整数n . 接下来n - 1 行,每

洛谷——P1351 联合权值

https://www.luogu.org/problem/show?pid=1351 题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离.对于图G 上的点对( u, v) ,若它们的距离为2 ,则它们之间会产生Wu×Wv 的联合权值. 请问图G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少? 输入输出格式 输入格式

[NOIP2014] 提高组 洛谷P1351 联合权值

题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离.对于图G 上的点对( u, v) ,若它们的距离为2 ,则它们之间会产生Wu ×Wv 的联合权值. 请问图G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少? 输入输出格式 输入格式: 输入文件名为link .in. 第一行包含1 个整数n . 接下来n - 1 行,

$Noip2014/Luogu1351$ 联合权值 树形

$Luogu$ $Description$ 给定一棵树,每两个距离为$2$的点之间可以产生"联合权值","联合权值"定义为这两个数的乘积.求最大的联合权值以及所有的联合权值之和.注意这两个数是有序的,翻译成人话就是求完和之后要$*2$. $Sol$ 想起了消防局的设立$ovo$. 距离为$2$的点,它们不是兄弟就是祖孙,那直接$dfs$一遍更新答案就好了叭. 兄弟之间更新答案这里有两个优化: 1.贪心.把所有的兄弟加入数组$s$之后按照$w[i]$从大到小排序,一遍

树的问题--P1351 联合权值

题目描述 无向连通图 GGG 有 nnn 个点,n−1n-1n−1 条边.点从 111 到 nnn 依次编号,编号为 iii 的点的权值为 WiW_iWi?,每条边的长度均为 111.图上两点 (u,v)(u, v)(u,v) 的距离定义为 uuu 点到 vvv 点的最短距离.对于图 GGG 上的点对 (u,v)(u, v)(u,v),若它们的距离为 222,则它们之间会产生Wv×WuW_v \times W_uWv?×Wu? 的联合权值. 请问图 GGG 上所有可产生联合权值的有序点对中,联合

Luogu P1351 联合权值 题解

这是一个不错的树形结构的题,由于本蒟蒻不会推什么神奇的公式其实是懒得推...,所以很愉快的发现其实只需要两个点之间的关系为祖父和儿子.或者是兄弟即可. 然后问题就变得很简单了,只需要做一个正常的DFS,遍历整棵树,同时判断有没有祖父,如果有就计算,然后遍历自己的儿子,每次判断最大的一个,然后用一个\(sum\)来维护这个点之前的所有兄弟的权值和,挨个计算即可. 具体操作见代码,如果有不懂的,代码里面具体解释. #include<bits/stdc++.h> #define clean(a,i)

洛谷【P1351】codevs3728 联合权值

题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离.对于图G 上的点对( u, v) ,若它们的距离为2 ,则它们之间会产生Wu×Wv 的联合权值. 请问图G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少? 输入输出格式 输入格式: 输入文件名为link .in. 第一行包含1 个整数n . 接下来n - 1 行,每

AC日记——联合权值 洛谷 P1351

题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离.对于图G 上的点对( u, v) ,若它们的距离为2 ,则它们之间会产生Wu ×Wv 的联合权值. 请问图G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少? 输入输出格式 输入格式: 输入文件名为link .in. 第一行包含1 个整数n . 接下来n - 1 行,