每一次枚举到重心 按子树中的黑点数SORT一下 启发式合并

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 2e6 + ;
const int MAXM = 2e6 + ;
int to[MAXM << ], nxt[MAXM << ], Head[MAXN], ed = ;
int cost[MAXM << ];
const int INF = ~0u >> ;
inline void addedge(int u, int v, int c)
{
to[++ed] = v;
cost[ed] = c;
nxt[ed] = Head[u];
Head[u] = ed;
}
inline void ADD(int u, int v, int c)
{
addedge(u, v, c);
addedge(v, u, c);
}
inline const int readin()
{
int r = , k = ;
char c = getchar();
for (; c < '' || c > ''; c = getchar()) if (c == '-') {
k = -;
}
for (; c >= '' && c <= ''; c = getchar()) {
r = r * + c - '';
}
return k * r;
}
int n, k, kk, m, anser, cnt, maxdep, summaxdep;
int sz[MAXN], f[MAXN], dep[MAXN], sumsz, root;
bool vis[MAXN];
int ok[MAXN], blasz[MAXN];
int h[MAXN], g[MAXN];
struct node {
int blaval;
int id;
} o[MAXN];
bool cmp(node a, node b)
{
return a.blaval < b.blaval;
}
void getroot(int x, int fa)
{
sz[x] = ;
f[x] = ;
for (int i = Head[x]; i; i = nxt[i]) {
int v = to[i];
if (v == fa || vis[v]) {
continue;
}
getroot(v, x);
sz[x] += sz[v];
f[x] = max(f[x], sz[v]);
}
f[x] = max(f[x], sumsz - sz[x]);
if (f[x] < f[root]) {
root = x;
}
}
void update(int x, int blanum, int deep, int fa)
{
if (blanum > kk) {
return ;
}
h[blanum] = max(h[blanum], deep);
for (int i = Head[x]; i; i = nxt[i]) {
int v = to[i];
if (vis[v] || v == fa) {
continue;
}
update(v, blanum + ok[v], deep + cost[i], x);
}
}
void getdeep(int x, int fa)
{
blasz[x] = ok[x];
for (int i = Head[x]; i; i = nxt[i]) {
int v = to[i];
if (v == fa || vis[v]) {
continue;
}
getdeep(v, x);
blasz[x] += blasz[v];
}
}
void calc(int x, int d)
{
cnt = ;
for (int i = Head[x]; i; i = nxt[i]) {
int v = to[i];
if (vis[v]) {
continue;
}
getdeep(v, x);
node now;
now.blaval = blasz[v];
now.id = i;
o[++cnt] = now;
}
}
void solve(int x)
{
summaxdep = -;
kk = k - ok[x];
int s;
vis[x] = ;
calc(x, );
sort(o + , o + cnt + , cmp);
for (int i = ; i <= cnt; i++) {
maxdep = -;
int depnow = o[i].blaval;
int v = to[o[i].id];
int c = cost[o[i].id];
s = min(depnow, kk);
for (int j = ; j <= s; j++) {
h[j] = -INF;
}
update(v, ok[v], c, x);
if (i == ) {
for (int j = ; j <= s; j++) {
g[j] = h[j];
}
} else {
for (int j = ; j <= s; j++) {
int aim = kk - j;
aim = min(aim, summaxdep);
if (h[j] != -INF && g[aim] != -INF) {
anser = max(anser, h[j] + g[aim]);
}
}
for (int j = ; j <= s; j++) {
g[j] = max(h[j], g[j]);
}
}
summaxdep = s;
for (int j = ; j <= summaxdep; j++) {
g[j] = max(g[j], g[j - ]);
}
}
anser = max(anser, g[min(kk, summaxdep)]);
int totsz = sumsz;
for (int i = Head[x]; i; i = nxt[i]) {
int v = to[i];
if (vis[v]) {
continue;
}
root = ;
sumsz = sz[v] > sz[x] ? totsz - sz[x] : sz[v];
getroot(v, );
solve(root);
}
}
int main()
{
cnt = anser = ;
n = readin(), k = readin(), m = readin();
for (int now, i = ; i <= m; i++) {
now = readin();
ok[now] = ;
}
int u, v, c;
for (int i = ; i < n; i++) {
u = readin(), v = readin(), c = readin();
ADD(u, v, c);
}
root = , sumsz = f[] = n;
getroot(, );
solve(root);
printf("%d\n", anser);
return ;
}

SPOJ 1825 经过不超过K个黑点的树上最长路径 点分治的更多相关文章

  1. spoj 1825 Free tour II

    http://www.spoj.com/problems/FTOUR2/ After the success of 2nd anniversary (take a look at problem FT ...

  2. SPOJ 1825 Free Tour | 终极之树分治

    求树上最长路径使得经过的拥挤节点个数不超过K //欢迎访问这个博客!http://www.cnblogs.com/luyouqi233/p/8036828.html #include<cstdi ...

  3. SPOJ 1825 Free tour II (树的点分治)

    题目链接 Free tour II 题意:有$N$个顶点的树,节点间有权值, 节点分为黑点和白点. 找一条最长路径使得 路径上黑点数量不超过K个 这是树的点分治比较基本的题,涉及树上启发式合并……仰望 ...

  4. [LeetCode] Max Sum of Rectangle No Larger Than K 最大矩阵和不超过K

    Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...

  5. [Swift]LeetCode363. 矩形区域不超过 K 的最大数值和 | Max Sum of Rectangle No Larger Than K

    Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...

  6. HDU 4417 Super Mario(主席树 区间不超过k的个数)题解

    题意:问区间内不超过k的个数 思路:显然主席树,把所有的值离散化一下,然后主席树求一下小于等于k有几个就行.注意,他给你的k不一定包含在数组里,所以问题中的询问一起离散化. 代码: #include& ...

  7. CF 给你三个数字L, R, K,问在[L, R]范围内有多少个数字满足它每一位不同数字不超过k个,求出它们的和(数位DP)

    题意: 给你三个数字L, R, K,问在[L, R]范围内有多少个数字满足它每一位不同数字不超过k个,求出它们的和 分析:考虑用状态压缩 , 10给位0~9 , 如果之前出现过了某个数字x ,那就拿当 ...

  8. Codeforces Round #466 (Div. 2) A. Points on the line[数轴上有n个点,问最少去掉多少个点才能使剩下的点的最大距离为不超过k。]

    A. Points on the line time limit per test 1 second memory limit per test 256 megabytes input standar ...

  9. BZOJ 4582 [Usaco2016 Open]Diamond Collector:贪心【相差不超过k】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4582 题意: 给你n个数. 让你将其中的一些数放入两个不同的集合中,并保证同一集合内两两元 ...

随机推荐

  1. PJzhang:python基础进阶的10个疗程-one

    猫宁!!! 课程导学 北京理工大学 国家精品在线开放课程 零基础.大学水平 100行左右的python可以做很多事情 编程是基本技能,体会思维 时间成本和收益的关系 每周5个小时 https://py ...

  2. Cowpatty 破解WPA-PSK加密

    一:使用wireshark 嗅探类工具打开之前抓的cpp中包含WPA握手的cap 文件,使用语法  eapol 进行过滤,可以看到抓取的Key数据 将其另存为保存到一个目录下. 二:而后就使用Cowp ...

  3. 【VS开发】socket编程原理

    socket编程原理 1.问题的引入 1) 普通的I/O操作过程: UNIX系统的I/O命令集,是从Maltics和早期系统中的命令演变出来的,其模式为打开一读/写一关闭(open-write-rea ...

  4. SQL ------ JDBC 删除指定的某条记录

    package demo; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; ...

  5. SSDsim

    1.官网 http://storage.hust.edu.cn/SSDsim/ 2.博客 http://www.tuicool.com/articles/U77n2i http://blog.sina ...

  6. sql中级语句

    创建联结 select n_title,n_content,t_name,t_memo from nrc_news,nrc_type where nrc_news.t_id=nrc_type.t_id ...

  7. 通过js判断整型,浮点型,布尔型,字符串型

    <!DOCTYPE html> <html > <head>     <meta charset="UTF-8">     < ...

  8. new与malloc有什么区别

    转自http://www.cnblogs.com/QG-whz/p/5140930.html 前言 几个星期前去面试C++研发的实习岗位,面试官问了个问题: new与malloc有什么区别? 这是个老 ...

  9. 【Python】【demo实验14】【练习实例】【斐波那契数列】【经典兔子生小兔子问题】

    古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 每个月的兔子数量 1:22:23:4 2+24:6 2+ ...

  10. 洛谷 P4137 Rmq Problem/mex 题解

    题面 首先,由于本人太菜,不会莫队,所以先采用主席树的做法: 离散化是必须环节,否则动态开点线段数都救不了你: 我们对于每个元素i,插入到1~(i-1)的主席树中,第i颗线段树(权值线段树)对于一个区 ...