SPOJ 1825 Free tour II 树分治
题意:
给出一颗边带权的数,树上的点有黑色和白色。求一条长度最大且黑色节点不超过k个的最长路径,输出最长的长度。
分析:
说一下题目的坑点:
- 定义递归函数的前面要加
inline
,否则会RE。不知道这是什么鬼,=_=|。 ans
要初始化为0,而不是一个绝对值很大的负数,因为我们可以选择只有一个顶点的路径,这样权值就是0。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#define MP make_pair
using namespace std;
typedef pair<int, int> PII;
const int maxn = 200000 + 10;
const int INF = 0x3f3f3f3f;
struct Edge
{
int v, w, nxt;
Edge() {}
Edge(int v, int w, int nxt): v(v), w(w), nxt(nxt) {}
};
int n, k, m, ans;
int black[maxn];
vector<int> a;
int ecnt, head[maxn];
Edge edges[maxn * 2];
inline void AddEdge(int u, int v, int w) {
edges[ecnt] = Edge(v, w, head[u]);
head[u] = ecnt++;
}
int fa[maxn], sz[maxn];
int dep[maxn], f[maxn], g[maxn], num[maxn];
bool del[maxn];
inline void dfs(int u) {
sz[u] = 1;
for(int i = head[u]; ~i; i = edges[i].nxt) {
int v = edges[i].v;
if(del[v] || v == fa[u]) continue;
fa[v] = u;
dfs(v);
sz[u] += sz[v];
}
}
inline PII findCenter(int u, int t) {
PII ans(INF, u);
int m = 0;
for(int i = head[u]; ~i; i = edges[i].nxt) {
int v = edges[i].v;
if(del[v] || v == fa[u]) continue;
m = max(m, sz[v]);
ans = min(ans, findCenter(v, t));
}
m = max(m, t - sz[u]);
return min(ans, MP(m, u));
}
inline void getdep(int u, int p) {
dep[u] = 0;
for(int i = head[u]; ~i; i = edges[i].nxt) {
int v = edges[i].v;
if(v == p || del[v]) continue;
getdep(v, u);
dep[u] = max(dep[u], dep[v]);
}
dep[u] += black[u];
}
bool cmp(int a, int b) { return dep[edges[a].v] < dep[edges[b].v]; }
inline void getg(int u, int p, int d, int c) {
g[c] = max(g[c], d);
for(int i = head[u]; ~i; i = edges[i].nxt) {
Edge& e = edges[i];
if(e.v == p || del[e.v]) continue;
getg(e.v, u, d + e.w, c + black[e.v]);
}
}
inline void solve(int u) {
fa[u] = 0;
dfs(u);
int s = findCenter(u, sz[u]).second;
del[s] = true;
for(int i = head[s]; ~i; i = edges[i].nxt) {
int v = edges[i].v;
if(del[v]) continue;
solve(v);
}
int tot = 0;
for(int i = head[s]; ~i; i = edges[i].nxt) {
int v = edges[i].v;
if(del[v]) continue;
getdep(v, s);
num[++tot] = i;
}
sort(num + 1, num + 1 + tot, cmp);
int mxdep = dep[edges[num[tot]].v];
for(int i = 0; i <= mxdep; i++) f[i] = -INF;
for(int i = 1; i <= tot; i++) {
int v = edges[num[i]].v, w = edges[num[i]].w;
int d = dep[v];
for(int j = 0; j <= d; j++) g[j] = -INF;
getg(v, s, w, black[v]);
if(i != 1) {
for(int j = 0; j <= k - black[s] && j <= d; j++) {
int j2 = min(dep[edges[num[i-1]].v], k - black[s] - j);
if(f[j2] == -INF) break;
if(g[j] != -INF) ans = max(ans, g[j] + f[j2]);
}
}
for(int j = 0; j <= d; j++) {
f[j] = max(f[j], g[j]);
if(j) f[j] = max(f[j], f[j-1]);
if(j + black[s] <= k) ans = max(ans, f[j]);
}
}
del[s] = false;
}
int main()
{
scanf("%d%d%d", &n, &k, &m);
while(m--) {
int x; scanf("%d", &x);
black[x] = 1;
}
ecnt = 0;
memset(head, -1, sizeof(head));
for(int i = 1; i < n; i++) {
int u, v, w; scanf("%d%d%d", &u, &v, &w);
AddEdge(u, v, w);
AddEdge(v, u, w);
}
ans = 0;
solve(1);
printf("%d\n", ans);
return 0;
}
SPOJ 1825 Free tour II 树分治的更多相关文章
- [spoj] FTOUR2 FREE TOUR II || 树分治
原题 给出一颗有n个点的树,其中有M个点是拥挤的,请选出一条最多包含k个拥挤的点的路径使得经过的权值和最大. 正常树分治,每次处理路径,更新答案. 计算每棵子树的deep(本题以经过拥挤节点个数作为d ...
- SPOJ 1825 Free tour II (树的点分治)
题目链接 Free tour II 题意:有$N$个顶点的树,节点间有权值, 节点分为黑点和白点. 找一条最长路径使得 路径上黑点数量不超过K个 这是树的点分治比较基本的题,涉及树上启发式合并……仰望 ...
- spoj 1825 Free tour II
http://www.spoj.com/problems/FTOUR2/ After the success of 2nd anniversary (take a look at problem FT ...
- SPOJ:Free tour II (树分治+启发式合并)
After the success of 2nd anniversary (take a look at problem FTOUR for more details), this 3rd year, ...
- 【SPOJ】1825. Free tour II(点分治)
http://www.spoj.com/problems/FTOUR2/ 先前看了一会题解就自己yy出来了...对拍过后交tle.................. 自己造了下大数据........t ...
- SPOJ 1825 Free Tour | 终极之树分治
求树上最长路径使得经过的拥挤节点个数不超过K //欢迎访问这个博客!http://www.cnblogs.com/luyouqi233/p/8036828.html #include<cstdi ...
- SPOJ FTOUR2 - Free tour II
Description 有些黑点,问你选择不超过 \(k\) 个黑点的路径,路径权值最大是多少. Sol 点分治. 这是qzc的论文题,不过我感觉他的翻译好强啊...我还是选择了自己去看题目... 点 ...
- SP1825 FTOUR2 - Free tour II 点分治+启发式合并+未调完
题意翻译 给定一棵n个点的树,树上有m个黑点,求出一条路径,使得这条路径经过的黑点数小于等于k,且路径长度最大 Code: #include <bits/stdc++.h> using n ...
- SPOJ1825 FTOUR2 - Free tour II
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
随机推荐
- c# 类名不同,字段相同,如何快速给类赋值
1,相关的两个类如下:现在我们知道短信的值,如何给微信来赋值呢,需要用到我们的反射,当然字段一一赋值也可以,但是如果字段有100个,这个方法就不行啦 /// <summary> /// 短 ...
- hubbledotnet 使用笔记
Hubble vs 字符串 <connectionStrings> <add name="Search" connectionString="serve ...
- SQL判断一个事件段 是否在数据库中与其他时间段有重叠 判断时间重叠
数据库字段startDate 开始时间 endDate 结束时间 -两个参数 比如查2-2 至2-6 在数据库中是否与其他时间有重叠 四个条件有一项满足则有重叠时间 思路是这样子 以开始和结束 ...
- springboot 学习笔记(三)
(三)用jar包启动springboot项目 1.首先需要在pom文件中添加依赖,spring-boot-starter-parent包含有打包的默认配置,如果要修改的话要可以进行重新定义,具体内容参 ...
- 在CentOS7上源码安装php7--Install php7 from source on CentOS7
首先下载php源码包并解压: # wget http://cn2.php.net/get/php-7.0.9.tar.gz/from/this/mirror # .tar.gz # cd php- 然 ...
- iOS VIPER架构(三)
路由是实现模块间解耦的一个有效工具.如果要进行组件化开发,路由是必不可少的一部分.目前iOS上绝大部分的路由工具都是基于URL匹配的,优缺点都很明显.这篇文章里将会给出一个更加原生和安全的设计,这个设 ...
- 在开发第一个Android应用之前需要知道的5件事:
你能否详细讲述一下,在开发Android应用过程中每一阶段要用到的技能和编程语言? 建立一个Android应用程序可以归结为两个主要技能/语言:Java和Android系统.Java是Android的 ...
- 获取元素Bytagname区别/for循环应用
一:两种获取元素方式的区别.1.var aLi = oUl.getElementsByTagName('li');TagName前面可以加其他东西,id就只能是document,2,Id是静态的,ta ...
- 【装载】删除Oracle11G
卸载Oracle步骤:1.停止所有与ORACLE相关的服务.2. 使用OUI(Oracle Universal Installer)卸载Oracle软件. “开始”->“程序”->“O ...
- PHP 解决同一个IP不同端口号session冲突的问题
在项目的开发阶段,我们经常会遇到几个站点共用同一个IP用不同端口号区分的形式!但是,这样很容易导致一个问题,session冲突丢失!即两个站点具有相同的session变量,清除session的时候即全 ...