树形dp

很明显我们可以枚举一条边,然后求两边的重心,这样是暴力,我们用一些奇怪的方法来优化这个找重心的过程,我们先预处理出来每个点最大和第二的儿子,然后每次把断掉的子树的贡献减掉,每次找重心就是向最大或第二大的儿子走,如果最大的儿子被减掉后比第二大的儿子小或者这条边被剪掉了,那么就向第二大的儿子走,这样复杂度是h的

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e4 + ;
int n;
ll ans = 1e18;
vector<int> G[N];
int dep[N], a[N], fa[N], son[N], bro[N];
ll sum[N], size[N];
void dfs(int u, int last)
{
size[u] = a[u];
fa[u] = last;
for(int i = ; i < G[u].size(); ++i)
{
int v = G[u][i];
if(v == last) continue;
dep[v] = dep[u] + ;
dfs(v, u);
size[u] += size[v];
sum[u] += sum[v] + size[v];
if(!son[u] || size[v] > size[son[u]]) bro[u] = son[u], son[u] = v;
else if(!bro[u] || size[v] > size[bro[u]]) bro[u] = v;
}
}
void center(ll &ret, int ban, ll tot, int u, ll S)
{
ret = min(ret, S);
int v = son[u];
if(v == ban || size[bro[u]] > size[v]) v = bro[u];
if(!v) return;
center(ret, ban, tot, v, S + tot - * size[v]);
}
void solve(int u, int last)
{
for(int i = ; i < G[u].size(); ++i)
{
int v = G[u][i];
if(v == last) continue;
for(int x = u; x; x = fa[x]) size[x] -= size[v];
ll tmp1 = 1e16, tmp2 = 1e16;
center(tmp1, v, size[], , sum[] - sum[v] - size[v] * dep[v]);
center(tmp2, , size[v], v, sum[v]);
ans = min(ans, tmp1 + tmp2);
for(int x = u; x; x = fa[x]) size[x] += size[v];
solve(v, u);
}
}
int main()
{
scanf("%d", &n);
for(int i = ; i < n; ++i)
{
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
for(int i = ; i <= n; ++i) scanf("%lld", &a[i]);
if(n <= )
{
puts("");
return ;
}
dfs(, );
solve(, );
printf("%lld\n", ans);
return ;
}

bzoj3302的更多相关文章

  1. BZOJ3302: [Shoi2005]树的双中心

    BZOJ3302: [Shoi2005]树的双中心 https://lydsy.com/JudgeOnline/problem.php?id=3302 分析: 朴素算法 : 枚举边,然后在两个连通块内 ...

  2. 【BZOJ3302】[Shoi2005]树的双中心 DFS

    [BZOJ3302][Shoi2005]树的双中心 Description Input 第一行为N,1<N<=50000,表示树的节点数目,树的节点从1到N编号.接下来N-1行,每行两个整 ...

  3. bzoj3302&bzoj2447&bzoj2103(树的重心)

    三倍的幸福! 暴力的做法就是枚举每一条边断开,选的两个点就是左右两棵树的重心. 可以发现找重心的时候一定是往权和大的子树找的,需要维护一个点的最大和次大子树,因为最大子树可能被割掉了,实际效率为O(N ...

随机推荐

  1. javafx中多场景的切换

    0.前言 前段时间在做javafx的应用程序,遇到一些坑.以本文记录之.(如有更好的解决办法欢迎评论,本人小白,轻喷) 1.问题 按照官方的中文文档,成功的运行了单一界面的表单登录.于是想自己试试多界 ...

  2. C#代码调用页面javascript函数

    C#代码调用javascript函数   前台<%@ Page Language="C#" AutoEventWireup="true" CodeFile ...

  3. IoT设备程序开发及编译环境搭建初体验

    引言 Mirai事件一经曝出,立即引领了一轮研究IoT设备的热潮.目前,对Mirai的报告大多只是在对其功能实现上的介绍,却很少提及如何实现IoT设备程序开发的测试环境.本文在对Mirai的源码研究的 ...

  4. SAP 锁对象 基本概念与基本操作 SE11

      一.SAP为什么要设置锁:     1,保持数据的一致性     假设几个用户要訪问相同的资源,须要找到一种同步訪问的方法去保持数据的一致性.比方说,在航班预订系统中,须要检查还有没有空座位,当检 ...

  5. jquery 获取下拉框 某个text='xxx'的option的属性 非选中 如何获得select被选中option的value和text和......

    jquery 获取下拉框 某个text='xxx'的option的属性 非选中 5 jquery 获取下拉框 text='1'的 option 的value 属性值 我写的var t= $(" ...

  6. 【数据结构】二叉树(c++)

    头文件: #include <iostream> using namespace std; template<class Type> class Bintree; //结点类 ...

  7. adb4robotium跨进程框架抛出InputStream cannot be null的异常的解决方案

    转自:http://blog.csdn.net/qingchunjun/article/details/43448371 之前我写的关于利用adb框架来进行robotium跨进程操作的文章中,有些朋友 ...

  8. Ajax_HTTP请求以及响应

    什么是HTTP请求? 就是从用户的浏览器端向服务器端发送请求 一个HTTP请求一般由四个部分组成 1.HTTP请求的方法或者动作,比如GET或者POST请求 2.请求的URL,也就是请求的地址 3.请 ...

  9. 图像处理之 opencv 学习---矩阵的操作

    OpenCV的一些操作,如生成随机矩阵,高斯矩阵,矩阵相乘之类的 /*功能:说明矩阵的一些操作方法*/#include "cv.h"//该头文件包含了#include " ...

  10. 利用easyUI的combobox打造自己主动提示组件

    自己主动提示是时下一个非常流行的功能,比方说百度.谷歌的搜索输入框都使用到了这么一个功能. 因为easyUI的combobox设计师已经考虑到了这个功能.所以仅仅需简单几步我们能够轻松打造自己的自己主 ...