可以发现,每个特殊点可以贡献的部分在树上是一条链。

设三元组(v,x,y)表示路径长度,需要更新的端点,与当前点的lca为y。

对于每个节点x,通过两遍树形DP可以求出:

d[x]:x到x子树内的某个特殊点的最优解。

u[x]:x到x子树外的某个特殊点的最优解。

pre[x]:x以及x之前的兄弟的d[]的最优解。

suf[x]:x以及x之后的兄弟的d[]的最优解。

然后在树上打标记,最后dfs一遍统计答案即可。

时间复杂度$O(n)$。

#include<cstdio>
#define N 100010
int n,m,i,x,y,z,vip[N],ans1,ans2;
int g[N],v[N<<1],w[N<<1],nxt[N<<1],ed,dis[N],q[N],t,tag[N],cnt[N];
struct P{
int v,x,y;
P(){v=-1;}
P(int _v,int _x,int _y){v=_v,x=_x,y=_y;}
}d[N],u[N],pre[N],suf[N],fin[N];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
void dfs1(int x,int f){
if(vip[x])d[x]=P(0,x,x);
for(int i=g[x];i;i=nxt[i])if(v[i]!=f){
int y=v[i];dis[y]=w[i];
dfs1(y,x);
if(d[y].v<0)continue;
if(d[y].v+w[i]>d[x].v)d[x]=d[y],d[x].v+=w[i];
else if(d[y].v+w[i]==d[x].v)d[x].x=x;
}
d[x].y=x;
fin[x]=d[x];
}
void dfs2(int x,int f){
if(vip[x]&&u[x].v<0)u[x]=P(0,x,x);
t=0;
for(int i=g[x];i;i=nxt[i])if(v[i]!=f)q[++t]=v[i];
for(int i=1;i<=t;i++){
int y=q[i];
pre[i]=pre[i-1];
if(d[y].v<0)continue;
if(d[y].v+dis[y]>pre[i].v)pre[i]=d[y],pre[i].v+=dis[y];
else if(d[y].v+dis[y]>pre[i].v)pre[i].x=x;
}
suf[t+1]=P();
for(int i=t;i;i--){
int y=q[i];
suf[i]=suf[i+1];
if(d[y].v<0)continue;
if(d[y].v+dis[y]>suf[i].v)suf[i]=d[y],suf[i].v+=dis[y];
else if(d[y].v+dis[y]>suf[i].v)suf[i].x=x;
}
for(int i=1;i<=t;i++){
int y=q[i];
P B=pre[i-1];
if(B.v<suf[i+1].v)B=suf[i+1];
else if(B.v==suf[i+1].v)B.x=x;
B.y=x;
if(B.v<u[x].v)B=u[x];
else if(B.v==u[x].v)B.x=x;
if(~B.v)B.v+=dis[y];
u[y]=B;
if(!vip[y])continue;
if(B.v>fin[y].v)fin[y]=B;
else if(B.v==fin[y].v)fin[y].v=-1;
}
for(int i=g[x];i;i=nxt[i])if(v[i]!=f)dfs2(v[i],x);
}
inline void modify(int x,int y,int z){tag[x]++,tag[y]++,tag[z]-=2,cnt[z]++;}
void dfs3(int x,int f){
for(int i=g[x];i;i=nxt[i])if(v[i]!=f)dfs3(v[i],x),tag[x]+=tag[v[i]];
cnt[x]+=tag[x];
}
int main(){
read(n),read(m);
for(i=1;i<=m;i++)read(x),vip[x]=1;
for(i=1;i<n;i++)read(x),read(y),read(z),add(x,y,z),add(y,x,z);
dfs1(1,0),dfs2(1,0);
for(i=1;i<=n;i++)if(vip[i])if(~fin[i].v)modify(i,fin[i].x,fin[i].y);
dfs3(1,0);
for(i=1;i<=n;i++)if(!vip[i]){
if(cnt[i]>ans1)ans1=cnt[i],ans2=1;
else if(cnt[i]==ans1)ans2++;
}
return printf("%d %d",ans1,ans2),0;
}

  

BZOJ4342 : CF348 Pilgrims的更多相关文章

  1. Codeforces-348E Pilgrims

    #4342. CF348 Pilgrims 此题同UOJ#11 ydc的大树 Online Judge:Bzoj-4342,Codeforces-348E,Luogu-CF348E,Uoj-#11 L ...

  2. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  3. 题解-CF348E Pilgrims

    题面 CF348E Pilgrims 有一棵 \(n\) 个点的 带权 树和 \(m\) 个关键点,要求杀了一个不关键的点,满足最多的关键点到离它最远的所有关键点的路径都被打断.求可以满足的最多关键点 ...

  4. 越狱Season 1- Episode 18: Bluff

    Season 1, Episode 18: Bluff -Michael: Scofield Scofield Michael Scofield Michael Scofield -Patoshik: ...

  5. python瓦登尔湖词频统计

    #瓦登尔湖词频统计: import string path = 'D:/python3/Walden.txt' with open(path,'r',encoding= 'utf-8') as tex ...

  6. 每日英语:Who Ruined The Humanities?

    You've probably heard the baleful reports. The number of college students majoring in the humanities ...

  7. A Child's History of England.28

    By such means, and by taxing and oppressing the English people in every possible way, the Red King b ...

随机推荐

  1. 虚拟机里面安装Openfiler 2.99

    简介 Openfiler 由rPath Linux驱动,它是一个基于浏览器的免费网络存储管理实用程序,可以在单一框架中提供基于文件的网络连接存储 (NAS) 和基于块的存储区域网 (SAN).Open ...

  2. linux 如何清理僵尸进程

    今天在维护服务器的时候,发现有5个nova-novncproxy的僵尸进程. 26327 ?        S      0:05  \_ /usr/bin/python /usr/bin/nova- ...

  3. Ubuntu 14.04/14.10下安装VMware Workstation 11图文教程

    VMware workstation 是一个可以进行桌面操作的虚拟软件.它可以让我们在一台电脑或者虚拟机中运行多个虚拟机. 由VMware公司研发和维护.由于是商业软件,我们需要买他们家的许可证或者说 ...

  4. OpenStack 的Nova组件详解

    Open Stack Compute Infrastructure (Nova) Nova是OpenStack云中的计算组织控制器.支持OpenStack云中实例(instances)生命周期的所有活 ...

  5. Cannot change version of project facet Dynamic web module to 2.5

    在工程目录下有一个.settings文件夹,打开org.eclipse.wst.common.project.facet.core.xml做如下修改:<installed facet=" ...

  6. 42.旋转数组的最小元素[Get min value of rotated array]

    [题目] 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个排好序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5 ...

  7. Java for LeetCode 143 Reorder List

    Given a singly linked list L: L0→L1→…→Ln-1→Ln, reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You must do th ...

  8. Enum:Backward Digit Sums(POJ 3187)

    反过来推 题目大意:就是农夫和这只牛又杠上了(怎么老是牛啊,能换点花样吗),给出一行数(从1到N),按杨辉三角的形式叠加到最后,可以得到一个数,现在反过来问你,如果我给你这个数,你找出一开始的序列(可 ...

  9. BestCoder14 1002.Harry And Dig Machine(hdu 5067) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5067 题目意思:给出一个 n * m 的方格,每一个小方格(大小为1*1)的值要么为 0 要么为一个正 ...

  10. codeforces A. Cinema Line 解题报告

    题目链接:http://codeforces.com/problemset/problem/349/A 题目意思:题目不难理解,从一开始什么钱都没有的情况下,要向每一个人售票,每张票价格是25卢布,这 ...