cogs2478 简单的最近公共祖先 树形dp

填坑……链接:http://cogs.pro/cogs/problem/problem.php?pid=2478

题意:求出:

日常题面不符系列……实际上这是个树归……从下向上,对于每个节点,他对于某个点做出的贡献就是子树的大小乘上(子树总大小减去这棵子树大小)再加上该点乘权值,用式子写就是$ans[root]=size[root]*(sum((size[root]-size[belong[v]]))+1)$。

递推即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=1000005;
 7 struct node
 8 {
 9     int from,to,next;
10 }edge[maxn<<1];
11 int head[maxn],tot;
12 void addedge(int u,int v)
13 {
14     edge[++tot]=(node){u,v,head[u]};head[u]=tot;
15 }
16 int weight[maxn],n,size[maxn];
17 long long ans=0;
18 void dfs(int root)
19 {
20     size[root]=1;
21     for(int i=head[root];i;i=edge[i].next)
22     {
23         int v=edge[i].to;
24         if(size[v])continue;
25         dfs(v);
26         ans+=1ll*size[v]*1ll*weight[root]*1ll*size[root];
27         size[root]+=size[v];
28     }
29     ans+=1ll*weight[root];
30 }
31 int haha()
32 {
33     freopen("easy_LCA.in","r",stdin);
34     freopen("easy_LCA.out","w",stdout);
35     scanf("%d",&n);
36     for(int i=1;i<=n;i++)scanf("%d",&weight[i]);
37     for(int i=1;i<n;i++)
38     {
39         int x,y;scanf("%d%d",&x,&y);
40         addedge(x,y);addedge(y,x);
41     }
42     dfs(1);
43     printf("%lld\n",ans);
44 }
45 int sb=haha();
46 int main(){;}

cogs2478

时间: 2024-10-25 11:38:22

cogs2478 简单的最近公共祖先 树形dp的相关文章

cogs 2478. [HZOI 2016]简单的最近公共祖先

2478. [HZOI 2016]简单的最近公共祖先 ★☆   输入文件:easy_LCA.in   输出文件:easy_LCA.out   简单对比时间限制:2 s   内存限制:128 MB [题目描述] 给定一棵有n个节点的有根树,根节点为1,每个节点有一个权值wi,求 即求所有无序节点对的LCA的权值之和. 树的节点编号为1~n,LCA表示两节点的最近公共祖先,即在它们的所有公共祖先中离根节点最远的节点. [输入格式] 第一行一个整数n,表示节点数. 第二行n个正整数,表示每个点的权值.

cojs 简单的最近公共祖先 解题报告

我曾经自己想过每考试一次就从考试题中找找idea来出题 这次又找到了一个,先不管原来的考试题是什么 考试题中其中的一部分就是今天的这道题目啦 当时考场上自己比较傻,没有注意到有用的性质,套用了之前黑白树系列的做法 写的是log^2n的,结果导致只能在开O2的情况下A掉这道题目 后来仔细研究了以下,得到了本题的做法 首先我们观察操作中和黑白树系列的那道题目的区别 1.只有染黑操作,没有染白操作 2.不需要可持久化,不需要满足可减性 之后观察题目的性质: 1.转化成暴力写法,每次修改u到根的路径,查

青云的机房组网方案(简单+普通+困难)(虚树+树形DP+容斥)

题目链接 1.对于简单的版本n<=500, ai<=50 直接暴力枚举两个点x,y,dfs求x与y的距离. 2.对于普通难度n<=10000,ai<=500 普通难度解法挺多 第一种,树形dp+LCA 比赛的时候,我猜测对于不为1的n个数,其中两两互质的对数不会很多,肯定达不到n^2 然后找出所有互质的对数,然后对为1的数进行特殊处理.(初略的估计了下,小于500的大概有50个质数,将n个数平均分到这些数中,最后大概有10000*50*200=10^7) 对所有的非1质数对,采用离

hdu 1520Anniversary party(简单树形dp)

Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4310    Accepted Submission(s): 1976 Problem Description There is going to be a party to celebrate the 80-th Anniversary of the

sgu 143 Long live the Queen 简单树形dp

// sgu 143  Long live the Queen 简单树形dp // // 题意:在树上选一个连通字图,使得节点的权值之和最大 // f[i] 表示以该节点为根的字图权值之和的最大值 // 则有 f[i] = w[i] + sigma(max(0,f[j])) i是j的父节点 // 最后在所有的f中挑个最大值就是答案.... #include <algorithm> #include <bitset> #include <cassert> #include

csu 2014 summer training day 3 简单树形dp

FZU 2157 题意:树上的节点可以打上0或1的标记,树的权值由两部分呢组成,点权和边权,有00.01.10.11四种组合的边权, 问最小权值和.以1节点为树根 分析:dp[x][0]表示x标记0后的最小的权值,dp[x][1]同理 那么每次可以计算dp[x][0],dp[x][1]: 例如dp[x][1]=min(dp[son][0]+lab[0][1]+val[1],dp[son][1]+bal[1][1]+val[1]); 具体看代码. 用bfs写的分层,深搜代码更简洁 1 #inclu

[Luogu P1122]最大子树和 (简单树形DP)

题面 传送门:https://www.luogu.org/problemnew/show/P1122 Solution 这是一道简单的树形DP题. 首先,我们可以转换一下题面,可以发现,题目要求我们求出一颗树上的最大联通子图. 因为我们是在树上取的,实际上就是取一颗子树. 这个就是最基础的树形DP模型了. 我们可以设f[i]表示我们选的子图以i为根所能取的子树的最大值. 转移是: f[i] = beauty[i] + xigema(max(f[j],0)) (也就是一颗树的孩子所能取的子树,如果

HDU 3899 简单树形DP

题意:一棵树,给出每个点的权值和每条边的长度, 点j到点i的代价为点j的权值乘以连接i和j的边的长度.求点x使得所有点到点x的代价最小,输出 虽然还是不太懂树形DP是什么意思,先把代码贴出来把. 这道题目的做法是:先进行一次DFS,以每个节点为根,求出它下面节点到它的数量和. 再进行一次DFS,以每个节点为根,求出它下面节点到它的花费总和. source code: #pragma comment(linker, "/STACK:16777216") //for c++ Compile

【leetcode 简单】 第六十八题 二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)." 例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5] _______6______ / ___2__ ___8__ / \ / 0 _4 7 9 / 3 5 示例 1: 输入: root