SP1825 FTOUR2 - Free tour II 点分治+启发式合并+未调完
题意翻译
给定一棵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 点分治+启发式合并+未调完的更多相关文章
- [spoj] FTOUR2 FREE TOUR II || 树分治
原题 给出一颗有n个点的树,其中有M个点是拥挤的,请选出一条最多包含k个拥挤的点的路径使得经过的权值和最大. 正常树分治,每次处理路径,更新答案. 计算每棵子树的deep(本题以经过拥挤节点个数作为d ...
- SPOJ:Free tour II (树分治+启发式合并)
After the success of 2nd anniversary (take a look at problem FTOUR for more details), this 3rd year, ...
- FTOUR2 - Free tour II
传送门 题目翻译的很清楚……似乎点分治的题题目描述都非常简洁. 还是那个操作,一条路径要么全部在一棵子树中,要么经过当前的重心,所以考虑点分治. 首先dfs求出重心的每一棵子树中,有i个黑点的最长路径 ...
- SPOJ Free TourII(点分治+启发式合并)
After the success of 2nd anniversary (take a look at problem FTOUR for more details), this 3rd year, ...
- SP1825 【FTOUR2 - Free tour II】
# \(SP1825\) 看到没有人用老师的办法,于是自己写一下思路 思路第一步:排除旧方法 首先这道题和\(4178\)不一样,因为那道题是计数,而这道题是求最值,最值有个坏处,就是对于来自相同子树 ...
- SPOJ1825 FTOUR2 - Free tour II
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- SPOJ FTOUR2 - Free tour II
Description 有些黑点,问你选择不超过 \(k\) 个黑点的路径,路径权值最大是多少. Sol 点分治. 这是qzc的论文题,不过我感觉他的翻译好强啊...我还是选择了自己去看题目... 点 ...
- SPOJ 1825 Free tour II 树分治
题意: 给出一颗边带权的数,树上的点有黑色和白色.求一条长度最大且黑色节点不超过k个的最长路径,输出最长的长度. 分析: 说一下题目的坑点: 定义递归函数的前面要加inline,否则会RE.不知道这是 ...
- spoj 1825 Free tour II
http://www.spoj.com/problems/FTOUR2/ After the success of 2nd anniversary (take a look at problem FT ...
随机推荐
- JS 缓冲运动 带运动的留言本 小案例
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- 关于卷积网络以及反卷积网络shape的计算
CNN的计算方式: w1 = (w - F_w + 2p) / s_w + 1 h1 = (h - F_h + 2p) / s_h + 1 其中 w, h 分别为上一层的宽高, Filters(ker ...
- mybatis+mysql返回插入的主键,参数只是提供部分参数
mybatis+mysql返回插入的主键,参数只是提供部分参数 <insert id="insertByChannelIdOpenid" useGeneratedKeys=& ...
- Uva 1331 - Minimax Triangulation(最优三角剖分 区间DP)
题目大意:依照顺时针或者逆时针的顺序给出多边的点,要将这个多边形分解成n-2个三角形,要求使得这些三角行中面积最大的三角形面积尽量小,求最小值. 思路:用区间DP能够非常方便解决,多边形可能是凹边形, ...
- Android 开源框架Universal-Image-Loader全然解析(一)--- 基本介绍及使用
转载请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/26810303).请尊重他人的辛勤劳动成果,谢谢! 大家好! ...
- Top10Servlet
<span style="font-size:18px;">/** * Top10 * author:杨鑫 */ package servlet; import jav ...
- Android 组件ContentProvider
Android 组件ContentProvider Android的数据存储有五种方式Shared Preferences.网络存储.文件存储.外储存储.SQLite,一般这些存储都仅仅是在单独的一个 ...
- Mongo 中间件 pre find 修改query
需求:在所有find查询的时候,默认添加查询参数 name:bennman //创建一个query中间件 myMid.js module.exports = function(schema){ //这 ...
- C#遍历DataSet与DataSet元素实现代码
C#中的Dataset就像一个数据库,有多个表(Table),一般只有一个表,然后每个表中有行(DataRow)和列(DataColumn),DataRow[DataColumn]可以得到某行某列数据 ...
- (Go)07.Go语言中strings和strconv包示例代码详解01
1.strings使用 前缀和后缀 HasPrefix判断字符串s是否以prefix开头: 示例: package main import ( "fmt" "string ...