Link:

POJ1935 传送门

Solution:

一道吓唬人的水题

注意这是一棵树,两点间仅有唯一的路径

于是每个“关键点”和起点只有一条路径,想去起点另一棵子树上的节点必须要回到起点

如果必须要回到起点,答案$res$就是除去无用边后整棵树总距离$*2$,

因为不必回到起点,最终结果为$res-mx$,$mx$为距起点的最远点的距离

除去无用边的方式:给每个“关键点”打上$vis$标记,这样最远点之后的点就不会被$dfs$到了

Code:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <utility>
#include <vector> using namespace std;
typedef pair<int,int> P;
#define X first
#define Y second
const int MAXN=5e4+;
vector<P> G[MAXN];
int n,k,root,dist[MAXN],vis[MAXN],mx,res,x,y,z; void dfs(int u,int anc)
{
for(int i=;i<G[u].size();i++)
{
int v=G[u][i].X;
if(v==anc) continue;
dist[v]=dist[u]+G[u][i].Y;
dfs(v,u);
if(vis[v]) vis[u]=true,res+=G[u][i].Y*; //传递标记
}
} int main()
{
scanf("%d%d",&n,&root);
for(int i=;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
G[x].push_back(P(y,z));G[y].push_back(P(x,z));
}
scanf("%d",&k);
for(int i=;i<=k;i++)
scanf("%d",&x),vis[x]=true; //打上标记
dfs(root,);
for(int i=;i<=n;i++)
if(vis[i]) mx=max(mx,dist[i]);
printf("%d",res-mx);
return ;
}

Review:

(1)对“树”这个条件中“两点之间只有一条路径”这个性质不够敏感,

因此未能看出到达一棵子树的最远点后必须要回到起点再出发这一推论

(2)除去无用边的方法很妙:设置$vis=true$,将更远的点截去

同时传递$vis$的值来更新答案

最新文章

  1. php获取用户 地区 、ip地址
  2. SQL性能优化案例分析
  3. 工作上遇到的问题 DEBUG 001
  4. View通用
  5. MySQL命令行导出数据库
  6. ArcGIS for Sever 10.1 服务迁移与恢复
  7. RabbitMQ介绍4 - 编程(C#客户端示例)
  8. Delphi 的运算符列表
  9. js密码的校验(判断字符类型、统计字符类型个数)
  10. 帝国cms灵动标签调用tags
  11. Visual studio 能否定位打开文件在项目中的位置
  12. JS读写浏览器cookie及读取页面参数
  13. Linux之安全应用
  14. java设计模式--简单工厂
  15. vue 配合vue-resource调用接口,获取数据
  16. matplot画图kill问题,形成思路
  17. ORM 框架简介
  18. Netty 零拷贝(一)NIO 对零拷贝的支持
  19. 递归计算一个目录的大小【os.wallk()】
  20. HDU 1754 I Hate It (线段树)

热门文章

  1. badboy录制提示当前页面的脚本发生错误
  2. Ubuntu15.04 python升级到python-3.6.x
  3. PHP vscode+XDebug 远程断点调试服务器上的代码
  4. Linux常用命令及工具记录(持续更新)
  5. Mini-MBA记录
  6. jQuery遍历 filter()方法
  7. 哈夫曼树(C++优先队列的使用)
  8. WeUI 在小程序中使用
  9. [洛谷P4588][TJOI2018]数学计算
  10. 纯css美化复选框,单选框,滑动条(range)