本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!

Description

After the success of 2nd anniversary (take a look at problem FTOUR for more details), this 3rd year, Travel Agent SPOJ goes on with another discount tour.

The tour will be held on ICPC island, a miraculous one on the Pacific Ocean. We list N places (indexed from 1 to N) where the visitors can have a trip. Each road connecting them has an interest value, and this value can be negative(if there is nothing interesting to view there). Simply, these N places along with the roads connecting them form atree structure. We will choose two places as the departure and destination of the tour.

Since September is the festival season of local inhabitants, some places are extremely crowded (we call themcrowded places). Therefore, the organizer of the excursion hopes the tour will visit at most K crowded places (too tiring to visit many of them) and of course, the total number of interesting value should be maximum.

Briefly, you are given a map of N places, an integer K, and M id numbers of crowded place. Please help us to find the optimal tour. Note that we can visit each place only once (or our customers easily feel bored), also the departure and destination places don't need to be different.

Input

There is exactly one case. First one line, containing 3 integers N K M, with 1 <= N <= 200000, 0 <= K <= M, 0 <= M <=N.

Next M lines, each line includes an id number of a crowded place.

The last (N - 1) lines describe (N - 1) two-way roads connected N places, form a b i, with a, b is the id of 2 places, and i is its interest value (-10000 <= i <= 10000).

Output

Only one number, the maximum total interest value we can obtain.

Example

Input:
8 2 3
3
5
7
1 3 1
2 3 10
3 4 -2
4 5 -1
5 7 6
5 6 5
4 8 3 Output:
12

Explanation

We choose 2 and 6 as the departure and destination place, so the tour will be 2 -> 3 -> 4 -> 5 -> 6, total interest value = 10 + (-2) + (-1) + 5 = 12 
* Added some unofficial cases

正解:树的点分治

解题报告:

  这道题需要统计树上经过黑点数量<=k的路径最长长度。

  这种树上的一类路经统计,很快能想到用树分治来做。
  考虑当$u$作为根时,我们仅统计经过$u$的所有路径,其余的递归处理。设$G[i]$表示之前的所有子树中经过黑点数量$<=i$的路径最长长度,$dep[i]$表示子节点$i$到其子树中经过的最大黑点数量。

  那么,我们可以枚举这次$dfs$的子节点,经过了多少个黑点$j$,那么可以与之组合的就是$G[k-black[u]-j]$,如果$<0$则跳过。

  容易发现我们每次统计完一棵子树之后,需要重新更新G,而G[i-1]又需要用G[i]更新,所以统计完这棵子树时,更新$G$和统计答案的复杂度是之前处理的所有节点的$max(dep[i])$,最坏情况可以变成每次都是$n^2$。

  考虑统计顺序不影响最终结果,那么我们可以按$dep[i]$排序,从小到大处理,则所有子树的$dep$之和显然$<=n$。

  总复杂度$O(nlog^2 n)$

  ps:我还是不是很懂为什么这组数据答案是0:

  1 0 1 
  1  

  

  这组数据应该没有合法的路径吧...开始一直WA,我调了好久结果特判掉这个点就过了...

//It is made by ljh2000
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <complex>
using namespace std;
typedef long long LL;
const int MAXN = 200011;
const int MAXM = 400011;
const int inf = (1<<30)-1;
int n,k,m,ecnt,first[MAXN],next[MAXM],to[MAXM],w[MAXM],black[MAXN];
bool use[MAXN];
int ans,tot,size[MAXN],S,nowL,nowg[MAXN];
int ansL,G[MAXN],maxd,dep[MAXN];//dep[x]表示x到子树内的所有节点中路径上黑点最多的数量
struct Tree{ int dep,x,z; }b[MAXN];
inline bool cmp(Tree q,Tree qq){ return q.dep<qq.dep; }
inline int getint(){
int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
} inline void dfs(int x,int fa){
size[x]=1; tot++;
for(int i=first[x];i;i=next[i]) {
int v=to[i]; if(v==fa || use[v]) continue;
dfs(v,x); size[x]+=size[v];
}
} inline void dfs2(int u,int fa,int &rt){
int maxl=0;
for(int i=first[u];i;i=next[i]) {
int v=to[i]; if(v==fa || use[v]/*!!!*/) continue;
dfs2(v,u,rt); maxl=max(maxl,size[v]);
}
if(tot-size[u]>maxl) maxl=tot-size[u];
if(rt==-1) S=maxl,rt=u;
else if(maxl<S) { S=maxl; rt=u; }
} inline void find_root(int u,int &rt){
tot=0; dfs(u,0); S=0;
dfs2(u/*!!!*/,0,rt); if(tot==1) rt=-1;
} inline void getdep(int x,int fa,int dd){
if(black[x]) dd++; if(dd>maxd) maxd=dd;
for(int i=first[x];i;i=next[i]) {
int v=to[i]; if(v==fa || use[v]/*!!!*/) continue;
getdep(v,x,dd);
}
} inline void dfs3(int x,int fa,int dep,int dd){
if(black[x]) dep++; if(dep>nowL) { nowL=dep; nowg[dep]=dd; }
else nowg[dep]=max(nowg[dep],dd); for(int i=first[x];i;i=next[i]) {
int v=to[i]; if(v==fa || use[v]/*!!!*/) continue;
dfs3(v,x,dep,dd+w[i]);
}
} inline void solve(int u){
int rt=-1; find_root(u,rt);
if(rt==-1) return ; int cnt=0;
u=rt; int now;
for(int i=first[u];i;i=next[i]) {
int v=to[i]; if(use[v]) continue;
maxd=0; getdep(v,u,0); dep[v]=maxd;
b[++cnt].x=v; b[cnt].dep=dep[v]; b[cnt].z=w[i];
}
sort(b+1,b+cnt+1,cmp); ansL=-1;
for(int o=1;o<=cnt;o++) {
int v=b[o].x; nowL=-1;
nowg[0]=-inf;//!!!
dfs3(v,u,0,b[o].z);
for(int i=1;i<=dep[v];i++) nowg[i]=max(nowg[i-1],nowg[i]);
if(ansL>=0) {//查询之前的最优值
for(int i=0;i<=dep[v];i++) {
if(nowg[i]==-inf) continue;
now=k-black[u]-i; if(now<0) break;
if(now>ansL) now=ansL;//!!!
ans=max(ans,G[now]+nowg[i]);
}
}
for(int i=0;i<=ansL;i++) G[i]=max(G[i],nowg[i]);
for(int i=nowL;i>ansL;i--) G[i]=nowg[i];
ansL=nowL;
for(int i=1;i<=ansL;i++) G[i]=max(G[i],G[i-1]);
}
for(int i=0;i<=ansL;i++) if(i+black[u]<=k) ans=max(ans,G[i]); else break; use[u]=1;
for(int i=first[u];i;i=next[i]) {//!!!
int v=to[i]; if(use[v]) continue;
solve(v);
}
} inline void work(){
n=getint(); k=getint(); m=getint(); int x,y,z;
for(int i=1;i<=m;i++) { x=getint(); black[x]=1; }
for(int i=1;i<n;i++) {
x=getint(); y=getint(); z=getint();
next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; w[ecnt]=z;
next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x; w[ecnt]=z;
}
ans=-inf; for(int i=0;i<=n;i++) G[i]=-inf;
solve(1);
if(ans==-inf) {
ans=0;
/*for(int i=1;i<=n;i++)
if(black[i]<=k) { ans=0; break; }*/
}
printf("%d",ans);
} int main()
{
work();
return 0;
}

  

SPOJ1825 FTOUR2 - Free tour II的更多相关文章

  1. 【SPOJ1825】Free tour II (点分治,启发式)

    题意: 边权可能为负 思路: 感觉我自己写的还是太过僵硬了,可以灵活一点,比如可以多写几个不同的dfs求出不同的信息,而不是压到同一个dfs里 #include<cstdio> #incl ...

  2. SPOJ FTOUR2 - Free tour II

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

  3. SPOJ1825:Free tour II

    题意 luogu的翻译 给定一棵n个点的树,树上有m个黑点,求出一条路径,使得这条路径经过的黑点数小于等于k,且路径长度最大 Sol 点分治辣 如果是等于\(k\)的话,开个桶取\(max\)就好了 ...

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

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

  5. FTOUR2 - Free tour II

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

  6. SP1825 FTOUR2 - Free tour II 点分治+启发式合并+未调完

    题意翻译 给定一棵n个点的树,树上有m个黑点,求出一条路径,使得这条路径经过的黑点数小于等于k,且路径长度最大 Code: #include <bits/stdc++.h> using n ...

  7. SP1825 【FTOUR2 - Free tour II】

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

  8. SPOJ 1825 Free tour II (树的点分治)

    题目链接 Free tour II 题意:有$N$个顶点的树,节点间有权值, 节点分为黑点和白点. 找一条最长路径使得 路径上黑点数量不超过K个 这是树的点分治比较基本的题,涉及树上启发式合并……仰望 ...

  9. SPOJ1825/FTOUR2:Free tour II——包看得懂/看不懂题解

    http://www.spoj.com/problems/FTOUR2/en/ 题目大意:给一棵黑白染色的树,求边权和最大且经过黑点不超过K的路径. ———————————————————— 前排膜拜 ...

随机推荐

  1. 巨蟒python全栈开发linux之centos5

    1.nginx安装使用 2.nginx访问日志和压测命令 3.nginx反向代理配置 nginx的404页面 访问:淘宝官网的一个错误地址:http://taobao.com/eeeeeeee 淘宝的 ...

  2. 巨蟒django之CRM3 添加和编辑客户&&公户和私户的展示和转换

    昨日内容回顾: day66 1. 内容回顾 1. 数据的展示 数据通过ORM查询出来 对象列表 QuerySet 1. 普通的字段 对象.字段名 ——> 数据库中的值 2. choices (( ...

  3. Springboot中jar 重复冲突 导致 静态资源加载问题!

    这个jar 其实在common 中也是存在的  ,当时没注意看,就导入进来了,然后  css js 等一些静态资源全部不能加载!具体原因我没去深挖!后面找个时间深挖下,先填坑!

  4. delphi下excel的操作

    1.首先引用comobj.varints单元 2.声明xlApp,xlBook, xlSheet,picture: Variant; 3.基本操作 xlApp:=CreateOleObject('Ex ...

  5. android自定义控件(三)ProgressBar

     1.ProgressBar有两个进度,一个是android:progress,另一个是android:secondaryProgress.比如视频的缓存进度以及播放进度. 在这里缓存的进度就可以是a ...

  6. Linux中的判断式

    格式一:test [参数] 判断内容格式二:[ [参数] 判断内容 ] 说明: a.格式二可以认为是格式一的缩写 b.格式二里中括号和内容之间要有空格 基于文件的判断-d 判断文件是否存在,并且是目录 ...

  7. linux crontab+curl+php 实现php定时任务

    首先登入Linux ->用root登入 在命令行输入 crontab -e  之后就会打开一个文件,并且是非编辑状态,则是vi的编辑界面,通过敲键盘上的i,进入编辑模式,就可以编辑内容.这个文件 ...

  8. ACM解题之快速输出杨辉三角形(前68行)

    题意: 本题要求计算并输出杨辉三角形的前 68 行. Time Limit:1000MS Memory Limit:65536K 解题: 为了能在规定时间准确输出杨辉三角形的前68行,这里我用了精准的 ...

  9. LeetCode:二叉树的层次遍历||【107】

    LeetCode:二叉树的层次遍历||[107] 题目描述 给定一个二叉树,返回其节点值自底向上的层次遍历. (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) 例如:给定二叉树 [3,9,2 ...

  10. offsetHeight+scrollHeight+clientHeight

    ch 窗口可见区域高度 :ch = padding + height(height不是所有内容的高度,是样式定义的高度) oh border以内的内容高度: oh = border + padding ...