• 洛谷 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 }
  • 相关阅读:
    二叉树中序遍历及后序遍历(下)
    完全二叉树和三序遍历算法(先序)(上)
    分布式调度——zookeeper
    Linux版JDK环境安装
    Redis的事务
    Redis的持久化——RDB与AOF
    分布式缓存——Redis
    非关系型数据库
    分布式存储——MySQL
    分布式系统
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/14429330.html
Copyright © 2020-2023  润新知