每一次枚举到重心 按子树中的黑点数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. ASP.NET Core 入门笔记10,ASP.NET Core 中间件(Middleware)入门

    一.前言 1.本教程主要内容 ASP.NET Core 中间件介绍 通过自定义 ASP.NET Core 中间件实现请求验签 2.本教程环境信息 软件/环境 说明 操作系统 Windows 10 SD ...

  2. MySQL知识篇-SQL3

    视图 1 提高重用性: 2 可用于数据库重构: 3 可用于不同用户,提高安全性: 定义视图: create view 视图name as select语句: 查看视图: show tables: 使用 ...

  3. 【Adobe Air程序开发】用Adobe Flex3开发AIR应用程序–入门指南

    1 安装Adobe AIR 运行时,和java的JVM类似.Adobe AIR 运行时允许在桌面运行AIR应用程序,脱离游览器的束缚.下载安装文件http://labs.adobe.com/downl ...

  4. phpstorm设置的快捷键突然失效了,提示: IdeaVim ...

    下班后,打开PHPstorm,突然感觉不对,经常用的快捷键突然用不了. 例如按了 Ctrl+F 快捷键后,提示:  IdeaVim! Using the Ctrl+F shortcut for Vim ...

  5. LeetCode之链表总结

    链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点来灵活地调整链表的长度.作为一种常用的数据结构,链表内置在很多高级编程语言里面.既比数组复杂又比树简单,所以链表经常被面试官 ...

  6. Response.write()弹出窗口的问题!

    今天偶然发现在.NET中使用Javascript语句弹出窗口时发现一个小小的问题! 例子如下: 1: Response.Write ("<script languge=javascri ...

  7. 洛谷P2622 关灯问题II (二进制枚举+bfs

    题目描述 现有n盏灯,以及m个按钮.每个按钮可以同时控制这n盏灯——按下了第i个按钮,对于所有的灯都有一个效果.按下i按钮对于第j盏灯,是下面3中效果之一:如果a[i][j]为1,那么当这盏灯开了的时 ...

  8. csp模拟赛低级错误及反思

    \(csp\)模拟赛低级错误及反思. 1.没开\(longlong\). 反思:注意数据类型以及数据范围. 2.数组越界(前向星数组未开两倍,一题的数据范围应用到另一题上,要开两倍的写法为开两倍数组) ...

  9. 购物车以php原生cookie实现

    index.php //入口文件 <?php /** * @name index.php * @decs * @author 老猫 <18368091722@163.com> * U ...

  10. CSP2019螺旋升天爆炸记

    Day -N 半年没碰OI的我终于又回到了这个熟悉又陌生的地方.然后颓废了两天就过了初赛? 初赛rp爆棚考了全校第一,然并卵 然后就是打了遍树状数组模板,写挂了(没错我现在连树状数组都会写挂) 看一眼 ...