很好的一道treedp,当然也挺烦的
首先不难想到先求出一个直径,然后穷举每条边,看他删除之后直径大小是否会变,变了的话就是必须经过的边
下面我们就要想怎么优化,本人语言表达略差,还是配合程序说吧。

 type node=record
point,next:longint;
cost:int64;
end; var f:array[..] of int64;
pr,fr:array[..,..] of longint;
g,h:array[..,..] of int64;
p:array[..] of longint;
edge:array[..] of node;
v:array[..] of boolean;
i,n,len,ans,x,y,z:longint; procedure add(x,y,z:longint);
begin
inc(len);
edge[len].point:=y;
edge[len].cost:=z;
edge[len].next:=p[x];
p[x]:=len;
end; function max(a,b:int64):int64;
begin
if a>b then exit(a) else exit(b);
end; procedure dp(x:longint);
var i,y:longint;
begin
i:=p[x];
v[x]:=true;
while i<>- do
begin
y:=edge[i].point;
if not v[y] then
begin
dp(y);
f[x]:=max(f[x],f[y]); //f[]表示以x为根的子树中最长的路径长
if g[y,]+edge[i].cost>g[x,] then //维护以x为根走到底最长的3条路径(显然不能有两条路径经过同一个孩子)
//这里要维护3条,因为要考虑删边的时候碰巧干掉了其中一条,如果单纯求树的直径的时候只要维护最长和次长即可)
begin
g[x,]:=g[x,];
fr[x,]:=fr[x,];
g[x,]:=g[x,];
fr[x,]:=fr[x,];
g[x,]:=g[y,]+edge[i].cost;
fr[x,]:=y; //从哪转移来的
end
else if (g[y,]+edge[i].cost>g[x,]) then
begin
g[x,]:=g[x,];
fr[x,]:=fr[x,];
g[x,]:=g[y,]+edge[i].cost;
fr[x,]:=y;
end
else if (g[y,]+edge[i].cost>g[x,]) then
begin
g[x,]:=g[y,]+edge[i].cost;
fr[x,]:=y;
end;
if f[y]>h[x,] then //h维护的是以x为根的子树中最长的2条路径(不经过根)
begin
h[x,]:=h[x,];
pr[x,]:=pr[x,];
h[x,]:=f[y];
pr[x,]:=y; //从哪转移来的
end
else if f[y]>h[x,] then
begin
h[x,]:=f[y];
pr[x,]:=y;
end;
end;
i:=edge[i].next;
end;
f[x]:=max(f[x],g[x,]+g[x,]);
end; procedure dfs(x:longint;l,d:int64); //l表示以x为终点且不是起点x的后辈的最长路径,d表示之前搜索到的不经过x的最长路径
var i,y:longint;
l1,l2,l3:int64;
begin
i:=p[x];
v[x]:=true;
while i<>- do
begin
y:=edge[i].point;
if not v[y] then //大批的分类讨论
begin
l1:=f[y];
if y=pr[x,] then l2:=h[x,]
else l2:=h[x,];
l2:=max(l2,d); if y=fr[x,] then l2:=max(l2,g[x,]+g[x,])
else if y=fr[x,] then l2:=max(l2,g[x,]+g[x,])
else l2:=max(l2,g[x,]+g[x,]); if y=fr[x,] then l3:=g[x,]
else l3:=g[x,];
l2:=max(l2,l+l3);
if max(l1,l2)<f[] then inc(ans);
dfs(y,max(l3,l)+edge[i].cost,l2);
end;
i:=edge[i].next;
end;
end; begin
readln(n);
fillchar(p,sizeof(p),);
for i:= to n- do
begin
readln(x,y,z);
add(x,y,z);
add(y,x,z);
end;
dp();
writeln(f[]);
fillchar(v,sizeof(v),false);
ans:=;
dfs(,,);
writeln(ans);
end.

bzoj3124的更多相关文章

  1. 【bzoj3124】 Sdoi2013—直径

    http://www.lydsy.com/JudgeOnline/problem.php?id=3124 (题目链接) 题意 求树的直径以及直径的交. Solution 我的想法超麻烦,经供参考..思 ...

  2. bzoj3124: [Sdoi2013]直径 树形dp two points

    题目链接 bzoj3124: [Sdoi2013]直径 题解 发现所有直径都经过的边 一定在一条直径上,并且是连续的 在一条直径上找这段区间的两个就好了 代码 #include<map> ...

  3. BZOJ3124 SDOI2013直径

    本以为必有高论,结果是个思博题.随便找一条直径,最后答案肯定是这条直径上的连续一段,如果某分支长度等于直径上某端的长度这一端都要被剪掉. #include<iostream> #inclu ...

  4. 【BZOJ3124】[Sdoi2013]直径 树形DP(不用结论)

    [BZOJ3124][Sdoi2013]直径 Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节 ...

  5. [bzoj3124] [Sdoi2013]直径

    看了child学长的题解才知道怎么写TAT http://www.cnblogs.com/ctlchild/p/5160272.html 以前不知道直径都是过重心的..代码改着改着就和标程完全一样了Q ...

  6. 2018.11.05 bzoj3124: [Sdoi2013]直径(树形dp)

    传送门 一道sbsbsb树形dpdpdp 第一问直接求树的直径. 考虑第二问问的边肯定在同一条直径上均是连续的. 因此我们将直径记下来. 然后对于直径上的每一个点,dpdpdp出以这个点为根的子树中不 ...

  7. bzoj千题计划134:bzoj3124: [Sdoi2013]直径

    http://www.lydsy.com/JudgeOnline/problem.php?id=3124 第一问: dfs1.dfs2 dfs2中记录dis[i]表示点i距离最长链左端点的距离 第二问 ...

  8. [BZOJ3124]直径

    Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅有N-1 条边. 路径:一 ...

  9. BZOJ3124 [Sdoi2013]直径 【树的直径】

    题目 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅有N-1 条边. 路径:一棵树上,任意两个节 ...

随机推荐

  1. 后缀自动机(SAM)

    *在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符 ...

  2. ueditor 添加微软雅黑字体 异常“从客户端中检测到有潜在危险的 request.form值”,解决

    使用ueditor往数据库添加文本内容时,如果字体有css样式, <,>," 这些字符会导致报出异常信息:从客户端中检测到有潜在危险的 request.form值 因为这些字符有 ...

  3. Intent.Action

    1 Intent.ACTION_MAIN String: android.intent.action.MAIN 标识Activity为一个程序的开始.比较常用. Input:nothing Outpu ...

  4. Java-Android 之应用停止错误

    在Android在手机上运行的时候: 经常会出现应用程序停止: 一: 因为触发的方法里面没有传值View 对象,方法报错

  5. [Session] SessionHelper---C#操作Session的帮助类 (转载)

    点击下载 SessionHelper.rar 下面是代码大家看一下 这个类主要是关于Session的基本操作比如:1.获取Session值2.设置一个Session的值3.清空所有的Session4. ...

  6. Android Studio中常用插件及浅释

    博客: 安卓之家 微博: 追风917 CSDN: 蒋朋的家 简书: 追风917 博客园:追风917 插件可以来这个仓库查找:Android Studio Plugins 这里给出几个平时常用到的as插 ...

  7. C# - winform使用Dictionary的时候,程序一闪而过!

    概述: 具体也不知道是多线程造成,还是Dictionary的缺陷. 解决方案: 1.如果可能会添加相同键值,你就别用add,直接添加键值,这样不报错 2.使用Try...catch可以捕获异常. 3. ...

  8. 如何在OpenWRT环境下做开发

    1.搭建开发环境 首先,在执行make menuconfig后,会出现下图: 其中,图中红框部分是我定制路由器的系统版本,大家可以根据不同的路由器进行不同的选择:绿框部分表示我们需要编译一个SDK开发 ...

  9. 在.Net中进行跨线程的控件操作(上篇:Control.Invoke)

    本文的重点在于介绍如何在多线程编程中,从非UI线程上访问界面中的控件.有过多线程编程经验的人都知道,当我们在非UI线程上试图给一个界面中的控件赋值的时候,比如说label的Text属性,系统会抛出一个 ...

  10. Win7使用IIS通过域名访问本地程序(网页、css、js等)

    一.目的:在本地浏览器里面,输入www.abc.com 可以访问我们本地搭建的网页程序 二.好处:在本地模拟,真实的访问,另外可以设置一些二级域名,例如static.abc.com域名用来存储像图片, ...