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

传送门


解题思路

先遍历一遍树,求出size[u](节点u的所有相邻节点的点权和),和图中联合权值的最大值。

如何求最大值?

求出每个点相连的点的第一大和第二大点权,相乘后与ans取max。

再求和:

再遍历一遍树,对于每个点u,答案加上w[u]*(size[v]-w[u])。

AC代码

复制代码
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<iomanip>
 5 #include<cmath>
 6 using namespace std;
 7 const int maxn=200005;
 8 const int mod=10007;
 9 int n,p[maxn],cnt,w[maxn],fa[maxn];
10 long long ans,size[maxn];
11 struct node{
12     int v,next;
13 }e[maxn*2];
14 void insert(int u,int v){
15     cnt++;
16     e[cnt].v=v;
17     e[cnt].next=p[u];
18     p[u]=cnt;
19 }
20 void dfs(int u,int f){
21     long long max1=0,max2=0;
22     fa[u]=f;
23     for(int i=p[u];i!=-1;i=e[i].next){
24         if(e[i].v!=f){
25             dfs(e[i].v,u);
26         }
27         size[u]+=w[e[i].v];
28         if(w[e[i].v]>max2) max2=w[e[i].v];
29         if(max2>max1) swap(max2,max1);
30     }
31     ans=max(ans,max1*max2); 
32 }
33 void dfs2(int u){
34     for(int i=p[u];i!=-1;i=e[i].next){
35         if(e[i].v!=fa[u]) dfs2(e[i].v);
36         ans+=w[u]*(size[e[i].v]-w[u]);
37     }
38 }
39 int main(){
40     memset(p,-1,sizeof(p));
41     cin>>n;
42     for(int i=1;i<n;i++){
43         int u,v;
44         scanf("%d%d",&u,&v);
45         insert(u,v);
46         insert(v,u);
47     }
48     for(int i=1;i<=n;i++) scanf("%d",&w[i]);
49     dfs(1,-1);
50     cout<<ans<<" ";
51     ans=0;
52     dfs2(1);
53     cout<<ans%mod;
54     return 0;
55 }
复制代码

 

作者:尹昱钦
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。

posted @   尹昱钦  阅读(82)  评论(0编辑  收藏  举报
编辑推荐:
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
阅读排行:
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 使用 Dify + LLM 构建精确任务处理应用
历史上的今天:
2020-02-22 洛谷 P1880 [NOI1995]石子合并(区间dp,断环为链)
2020-02-22 洛谷 P1901 发射站(单调栈)
点击右上角即可分享
微信分享提示