每一次枚举到重心 按子树中的黑点数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. docker清理

    # 删除退出的容器docker rm $(docker ps -qa --no-trunc --filter "status=exited") # 删除悬挂镜像docker rmi ...

  2. K/3 Cloud 中FID和FMasterID的区别

    经常会用到,例如物料在多组织情况下. 例如一个物料分配不同组织后,内码FID肯定是不同的,但FMaterId还是一样的,因为是用一个物料. FMASTERID是和物料编码对应的内码,即一个物料编码对应 ...

  3. SSRF绕过姿势

    0x00 什么是SSRF? SSRF(Server-Side Request Forgery,服务器端请求伪造):是一种由攻击者构造形成由服务器端发起请求的一个漏洞. SSRF 攻击的目标是从外网无法 ...

  4. poj1905 Expanding Rods(二分)

    题目链接:https://vjudge.net/problem/POJ-1905 题意:有一根长len的木棍,加热了n度,长度会膨胀为len*(1+n*c),c为膨胀系数.现在把这根木棍夹在两堵墙之间 ...

  5. [转帖]Linux 下实践 VxLAN:虚拟机和 Docker 场景

    Linux 下实践 VxLAN:虚拟机和 Docker 场景 https://www.cnblogs.com/bakari/p/11264520.html 实践了下 没问题 作者写的很perfect ...

  6. Plsql配置后,sql语句可以简写 快速使用

    in=INSERT up=UPDATE se=SELECT fr=FROM wh=WHERE or=ORDER BY de=DELETE df=DELETE FROM sf=SELECT * FROM ...

  7. SQL Server优化技巧——如何避免查询条件OR引起的性能问题

    原文:SQL Server优化技巧--如何避免查询条件OR引起的性能问题 之前写过一篇博客"SQL SERVER中关于OR会导致索引扫描或全表扫描的浅析",里面介绍了OR可能会引起 ...

  8. Boot-crm管理系统开发教程(三)

    (ps:前两章我们已经把管理员登录和查看用户的功能实现了,那么今天我们将要实现:添加用户,删除用户,和修改用户功能) 由于Cusomer的POJO类型已经写好了,所以这次我们之前从CustomerCo ...

  9. audio隐藏下载按钮

    // 这个方法只支持 Chrome 58+, 低于该版本的是没有无法隐藏的 <audio src="/i/horse.ogg" controls="controls ...

  10. charles 抓包 (一)

    在web.app开发中经常需要通过抓包来定位页面.接口返回数据的问题.在mac系统中,charles是一款功能丰富的抓包软件.可以实现app的数据抓包. 工具:charles 附送charles的破解 ...