这道题用到了4个dfs,分别是找出所有家的最小生成树,找出一点距离树的最小距离,找出每个点儿子距离的最大值(不包括父亲,也就是指不包括根节点的子树),用父亲的值来更新自己

因为我们可以知道:如果我们在树上,那么最短的距离就是树的长度的两倍-距自己最远的点的距离,当我们不在树上时,就得先走到树上(这条路径是唯一的),然后再重复刚才的过程

找出生成树比较简单,重点是找出距树上一点最远的点的距离,这里先找出除了父亲之外每个子树的距离,求出最大和第二,然后再用父亲更新自己的距离,很难想到

#include<iostream>
#include<stdio.h>
#include<string.h>
#define N 1000010
using namespace std;
typedef long long ll;
ll tot;
int cnt=-;
int head[N],to[N],next[N],w[N],used[N],nearest_node[N];
ll dis[N],max_dis[N],sec_dis[N],min_dis[N];
int max_dis_node[N],sec_dis_node[N];
bool k[N],on_tree[N]; void insert(int u,int v,int c)
{
next[++cnt]=head[u];
head[u]=cnt;
to[cnt]=v;
w[cnt]=c;
} ll max(ll x,ll y)
{
return x>y?x:y;
} ll min(ll x,ll y)
{
return x<y?x:y;
} void init()
{
memset(head,-,sizeof(head));
memset(to,-,sizeof(to));
memset(next,-,sizeof(next));
memset(used,,sizeof(used));
memset(on_tree,false,sizeof(on_tree));
memset(min_dis,,sizeof(min_dis));
memset(nearest_node,,sizeof(nearest_node));
memset(dis,,sizeof(dis));
memset(max_dis,,sizeof(max_dis));
} bool dfs1(int u)//找树
{
used[u]=;
for(int i=head[u];~i;i=next[i])
{
int v=to[i];
if(!used[v])
{
bool f2=dfs1(v);
if(f2)
{
on_tree[u]|=f2;
tot+=w[i];
}
dfs1(v);
}
}
return on_tree[u];
} void dfs2(int u)//找树距
{
used[u]=; if(on_tree[u]) nearest_node[u]=u;
for(int i=head[u];~i;i=next[i])
{
int v=to[i];
if(!on_tree[v]&&!used[v])
{
min_dis[v]=min_dis[u]+w[i];
nearest_node[v]=nearest_node[u];
}
if(!used[v]) dfs2(v);
}
} ll dfs3(int u)//儿子的最大距离
{
used[u]=;
for(int i=head[u];~i;i=next[i])
{
int v=to[i];
if(!used[v]&&on_tree[v])
{
ll dis=dfs3(v)+w[i];
if(dis>max_dis[u])
{
sec_dis[u]=max_dis[u];
max_dis[u]=dis;
max_dis_node[u]=v;
}
else if(dis>sec_dis[u])
{
sec_dis[u]=dis;
}
}
}
return max_dis[u];
} void dfs4(int u,ll last_max)
{
used[u]=;
for(int i=head[u];~i;i=next[i])
{
int v=to[i];
ll temp=max(last_max,max_dis[u]);
dis[u]=max(last_max,max_dis[u]);
if(!used[v]&&on_tree[v])
{
if(max_dis_node[u]==v)
{
dfs4(v,max(last_max,sec_dis[u])+w[i]);
}
else dfs4(v,max(last_max,max_dis[u])+w[i]);
}
}
} int main()
{
init();
int n,k; scanf("%d%d",&n,&k);
for(int i=;i<n;i++)
{
int u,v,c; scanf("%d%d%d",&u,&v,&c);
insert(u,v,c); insert(v,u,c);
}
int x;
for(int i=;i<=k;i++)
{
scanf("%d",&x); on_tree[x]=true;
}
dfs1(x); memset(used,,sizeof(used));
dfs2(x); memset(used,,sizeof(used));
dfs3(x); memset(used,,sizeof(used));
dfs4(x,);
/* printf("tot=%d\n",tot);
printf("-------------\n");
for(int i=1;i<=n;i++)
printf("%d ",dis[i]);
printf("\n------------\n"); */
for(int i=;i<=n;i++)
printf("%lld\n",*tot+min_dis[i]-dis[nearest_node[i]]);
return ;
}

bzoj 3743的更多相关文章

  1. bzoj 3743 [ Coci 2015 ] Kamp —— 树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 一开始想到了树形DP,处理一下子树中的最小值,向上的最小值,以及子树中的最长路和向上的 ...

  2. bzoj 3743 [Coci2015]Kamp——树形dp+换根

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 树形dp+换根. “从根出发又回到根” 减去 “mx ” . 注意dfsx里真的要改那 ...

  3. bzoj 3743: [Coci2015]Kamp【树形dp】

    两遍dfs一遍向下,一边向上,分别记录子树内人数a,当前点到所有点的距离b,最大值c和次大值d,最大值子树p 然后答案是2b-c #include<iostream> #include&l ...

  4. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  5. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  6. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  7. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  8. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

  9. 【sdoi2013】森林 BZOJ 3123

    Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...

随机推荐

  1. 如何配置QuickFIX/N

    Acceptor或者Initiator能够为您维护尽可能多的FIX会话,因而FIX会话标识的唯一性非常重要.在QuickFIX/N中,一个FIX会话的唯一标识是由:BeginString(FIX版本号 ...

  2. Xcode 编译的哪些错误

    1.error: macro names must be identifiers YourProject_prefix.pch 原因: 因为你弄脏了预处理器宏,在它处于<Multiple Val ...

  3. 为什么做前端要做好SEO

    我就挑干货说啦SEO可能听起来很高大上,其实翻译成中文就是"搜索引擎优化",它只是通过一定的方法在网站内外发布文章.交换连接等,最终达到某个关键词在搜索引擎上获得好的排名. 我有幸 ...

  4. 苹果IOS开发者账号总结--发布应用APP时team name是否可以随意写?

    个人账号(Individual): 费用99美金一年, 该账号在App Store销售者只能显示个人的ID,比如zhitian zhang,单人使用.个人账号只能有一个开发者.100个苹果的iOS设备 ...

  5. MySQL数据库的优化(下)MySQL数据库的高可用架构方案

    MySQL数据库的优化(下)MySQL数据库的高可用架构方案 2011-03-09 08:53 抚琴煮酒 51CTO 字号:T | T 在上一篇MySQL数据库的优化中,我们跟随笔者学习了单机MySQ ...

  6. Android开发之旅: Intents和Intent Filters(理论部分)

    引言 大部分移动设备平台上的应用程序都运行在他们自己的沙盒中.他们彼此之间互相隔离,并且严格限制应用程序与硬件和原始组件之间的交互. 我们知道交流是多么的重要,作为一个孤岛没有交流的东西,一定毫无意义 ...

  7. Word中的字体大小

    Word中的字体大小(几号-几磅)   Word对字体大小采用两种不同的度量单位,其中一种是以"号"为度量单位,如常用的"初号.小初.一号.小一--七号.八号" ...

  8. JBOSS只能本机localhost和127.0.0.1能访问的解决

    一句话: %jboss_home%\bin>standalone.bat -Djboss.bind.address=0.0.0.0 也可以直接编辑standalone.xml,将里面所有127. ...

  9. 简单谈谈dom解析xml和html

    前言 文件对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标志语言的标准编程接口.html,xml都是基于这个模型构造的.这也是一个W3C推出的标准.j ...

  10. Qt中的qreal

    在桌面操作系统中(比如Windows, XNix等)qreal其实就是double类型:而在嵌入设备系统中,qreal则等同于float 类型.