每一次枚举到重心 按子树中的黑点数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. guns系统部署方式及常见问题

    项目框架:guns 开发IDE:Idea 2018.1 两种打包方式:war 和jar. 1.正常打包的姿势 1.1按照下图修改为你想到打包的方式. ​ 1.2 执行打包 ​​ clean packa ...

  2. django 之(一) --- DjangoRestFormwork

    接口概念 IOP:面向接口编程,不再关注具体的实现:只关注输入.输出. http://www.ruanyifeng.com/blog/2018/10/restful-api-best-practice ...

  3. Dlib支持CPU指令集编译问题(SSE4.2或者AVX)

    The compile script is: mkdir build cd build cmake ../../tools/python -DUSE_SSE2_INSTRUCTIONS=ON cmak ...

  4. ValueError: Object arrays cannot be loaded when allow_pickle=False

    错误ValueError: Object arrays cannot be loaded when allow_pickle=False的解决     numpy最新版1.17以上版本与其他包不兼容问 ...

  5. Navicat Premium12 注册机下载及教程

    1.下载Navicat Premium 官网https://www.navicat.com.cn/下载最新版本下载安装(文末,网盘地址有64位安装包和注册机下载) 2.激活Navicat Premiu ...

  6. ZOJ Problem Set - 1002

    参考: 1.http://www.cnblogs.com/phinecos/archive/2008/09/18/1293017.html 基本思想:回溯法 重点在void Solve(int k,i ...

  7. js-转换方式示例

    var person1 = { toLocaleString : function () { return "Baraka"; }, toString : function() { ...

  8. java实验题目

    1. 打印输出所有的“水仙花数”,所谓“水仙花数”是指一个3位数,其中各位数字立方和等于该数本身.例如,153是一个“水仙花数”. 实验源码: public class number1 { publi ...

  9. Oracle-DQL 4- 多表查询

    多表查询: 1.笛卡尔积SELECT * FROM dept;--查询员工的信息和其所在部门的信息SELECT ename,job,dname,locFROM emp,dept; --集合A中的所有元 ...

  10. SQLSERVER2008 内存占用高的处理方式

    原文:SQLSERVER2008 内存占用高的处理方式 方法一: 方法二: 使用以下语句查找出什么语句占内存最高,针对占内存高的语句进行优化SELECT SS.SUM_EXECUTION_COUNT, ...