题意翻译

给定一棵n个点的树,树上有m个黑点,求出一条路径,使得这条路径经过的黑点数小于等于k,且路径长度最大

Code:

#include <bits/stdc++.h>
using namespace std;
#define pr pair<int, int>
#define mp make_pair
const int maxn = 2000003;
const int inf = 1000000000;
void setIO(string a)
{
string in = a + ".in", out = a + ".out";
freopen(in.c_str(), "r", stdin);
}
vector <pr> vrr;
int edges, n, m, K, ans, mdep, tl, root = 0, sn;
int hd[maxn], to[maxn << 1], nex[maxn << 1], val[maxn << 1], siz[maxn];
int mk[maxn], vis[maxn], mine[maxn], dis[maxn], tmp1[maxn], tmp2[maxn], f[maxn];
void add(int u, int v, int c)
{
nex[++edges] = hd[u], hd[u] = edges, to[edges] = v, val[edges] = c;
}
void Getroot(int u, int ff)
{
siz[u] = 1, f[u] = 0;
for(int i = hd[u]; i ; i = nex[i])
{
int v = to[i];
if(v == ff || vis[v]) continue;
Getroot(v, u);
siz[u] += siz[v], f[u] = max(f[u], siz[v]);
}
f[u] = max(sn - siz[u], f[u]);
if(f[u] < f[root]) root = u;
}
void getmax(int x, int ff, int d1)
{
siz[x]=1;
mdep = max(mdep, d1 + mk[x]);
for(int i = hd[x]; i ; i = nex[i])
{
int v = to[i];
if(vis[v] || v == ff) continue;
dis[v] = dis[x] + val[i];
getmax(v, x, d1 + mk[x]);
siz[x]+=siz[v];
}
}
void getdis(int x, int ff, int d2)
{
if(d2 > K) return ;
tmp1[++tl] = dis[x], tmp2[tl] = d2 + mk[x];
for(int i = hd[x]; i ; i = nex[i])
{
int v = to[i];
if(v == ff || vis[v]) continue;
getdis(v, x, d2 + mk[x]);
}
}
void calc(int x)
{
if(mk[x]) --K;
vrr.clear();
siz[x]=1;
for(int i = hd[x]; i ; i = nex[i])
{
int v = to[i];
if(vis[v]) continue;
mdep = 0, dis[v] = val[i];
getmax(v, x, 0);
siz[x]+=siz[v];
vrr.push_back(mp(mdep, v));
}
sort(vrr.begin(), vrr.end());
tl = mine[0] = 0;
// printf("%d ::: ",x);
for(int sz = vrr.size(), i = 0; i < sz; ++i)
{
int cur = vrr[i].second;
int pdl = tl;
getdis(cur, x, 0);
for(int j = pdl + 1; j <= tl; ++j)
if(K >= tmp2[j])
ans = max(ans, mine[K - tmp2[j]] + tmp1[j]);
// printf("%d ",vrr[i].second);
// tmp2[j] :: 有tmp2[j]个黑子时的最大值.
for(int j = pdl + 1; j <= tl; ++j) mine[tmp2[j]] = max(mine[tmp2[j]], tmp1[j]);
for(int j = 1; j <= vrr[i].first; ++j) mine[j] = max(mine[j-1],mine[j]);
}
// printf("\n");
if(vrr.size())
for(int i=1;i<=vrr[vrr.size()-1].first;++i) mine[i] = -inf;
if(mk[x]) ++K;
}
void solve(int u)
{
vis[u] = 1;
calc(u);
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(vis[v]) continue;
root=0,sn=siz[v];
Getroot(v,u);
solve(root);
}
}
int main()
{
// setIO("input");
scanf("%d%d%d",&n, &K, &m);
for(int i = 1,o; i <= m ; ++i)
{
scanf("%d",&o);
mk[o] = 1;
}
for(int i = 1; i < n ; ++i)
{
int u, v, c;
scanf("%d%d%d",&u, &v, &c);
add(u, v, c), add(v, u, c);
}
for(int i=1;i<maxn;++i) mine[i]=-inf;
sn = n, f[0] = inf;
Getroot(1, 0); solve(root);
printf("%d\n",ans);
return 0;
}

  

SP1825 FTOUR2 - Free tour II 点分治+启发式合并+未调完的更多相关文章

  1. [spoj] FTOUR2 FREE TOUR II || 树分治

    原题 给出一颗有n个点的树,其中有M个点是拥挤的,请选出一条最多包含k个拥挤的点的路径使得经过的权值和最大. 正常树分治,每次处理路径,更新答案. 计算每棵子树的deep(本题以经过拥挤节点个数作为d ...

  2. SPOJ:Free tour II (树分治+启发式合并)

    After the success of 2nd anniversary (take a look at problem FTOUR for more details), this 3rd year, ...

  3. FTOUR2 - Free tour II

    传送门 题目翻译的很清楚……似乎点分治的题题目描述都非常简洁. 还是那个操作,一条路径要么全部在一棵子树中,要么经过当前的重心,所以考虑点分治. 首先dfs求出重心的每一棵子树中,有i个黑点的最长路径 ...

  4. SPOJ Free TourII(点分治+启发式合并)

    After the success of 2nd anniversary (take a look at problem FTOUR for more details), this 3rd year, ...

  5. SP1825 【FTOUR2 - Free tour II】

    # \(SP1825\) 看到没有人用老师的办法,于是自己写一下思路 思路第一步:排除旧方法 首先这道题和\(4178\)不一样,因为那道题是计数,而这道题是求最值,最值有个坏处,就是对于来自相同子树 ...

  6. SPOJ1825 FTOUR2 - Free tour II

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  7. SPOJ FTOUR2 - Free tour II

    Description 有些黑点,问你选择不超过 \(k\) 个黑点的路径,路径权值最大是多少. Sol 点分治. 这是qzc的论文题,不过我感觉他的翻译好强啊...我还是选择了自己去看题目... 点 ...

  8. SPOJ 1825 Free tour II 树分治

    题意: 给出一颗边带权的数,树上的点有黑色和白色.求一条长度最大且黑色节点不超过k个的最长路径,输出最长的长度. 分析: 说一下题目的坑点: 定义递归函数的前面要加inline,否则会RE.不知道这是 ...

  9. spoj 1825 Free tour II

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

随机推荐

  1. [bzoj1925][Sdoi2010]地精部落_递推_动态规划

    地精部落 bzoj-1925 Sdoi-2010 题目大意:给你一个数n和模数p,求1~n的排列中满足每一个数的旁边两个数,要么一个是边界,要么都比它大,要么都比它小(波浪排列个数) 注释:$1\le ...

  2. 配置sublime text 前端环境

    SublimeLinter是Sublime的一个代码检测工具插件.安装前台是配置好node环境 1,在sublime text安装 SublimeLinter 按下 Ctrl+Shift+p 进入 C ...

  3. What you can talk

    data buffer who locked the account hash join cost memory and nested loop do not. How to make it hash ...

  4. Clojure:添加gzip功能

    利用现有的插件,在Clojure中添加gzip的功能是很方便的.1.    在project.clj中添加对bk/ring-gzip插件的依赖.:dependencies [bk/ring-gzip ...

  5. spark之map与flatMap差别

    scala> val m = List(List("a","b"),List("c","d")) m: List[ ...

  6. unity中 拖拽随意的对象

    孙广东   2015.8.16 目的 :  我们能简单的通过 鼠标位置 得到目标对象  假设没有使用刚体组件 Step - 1: 在3D项目中设置场景.  一个空对象命名为: DragAndDrop ...

  7. Struts 配置文件

    web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="htt ...

  8. android按钮被点击文字颜色变化效果

    有的时候做应用需要点击按钮时文字颜色也跟着变,松开后又还原,目前发现两种解决方案:第一用图片,如果出现的地方比较多,那么图片的量就相当可观:第二,也就是本文讲到的.废话少说,先贴图片,再上代码. 正常 ...

  9. 辨异 —— Java 中 String 的相等性比较

    How do I compare strings in Java? 1. 语法知识 ==:判断的是引用的相等性(reference equality),也即是否为同一对象: .equals():判断的 ...

  10. bzoj3033 太鼓达人——欧拉图搜索

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3033 考虑那 (1<<k) 个数,要形成答案,必然是相邻两个数间有 k-1 个重 ...