树的直径,树的最长路dp思想

dp一直弱死了,树型dp很多基本的题都不会,最近在刷树型dp的题,把关于树的最长路的思想总结一下:

树的直径:树中距离最远的两点间的距离。

下面说几道题:

hdu 2196:对于树上(双向边)的每一个节点求出与其距离最远的点的距离。

这个主要用的思想是两次dfs:一次dfs将无向图转化为有跟树(所以一开是一定要是建双向边,不然很可能wa或者tle,记录过程中可以开数组记入父亲节点,也可以在dfs递推过程中以栈的形式记录)求出每个跟节点到其所有的叶子节点的最远距离f[i]和g[i]。再一次dfs求出能够由父亲节点转化得到的最大距离h[i],求h[i]的过程中就有可能用到f[i]和g[i]了,因为如果i节点在其父亲j节点的最远距离f[j]中,那么f[i]就只能由g[j]或者h[j]得到,不然就由f[j]或者h[j]得到,具体可能说的不是特别清。两个dfs综合起来的复杂度只有O(E)

poj 1985:求树的直径。个人觉得大概有3种方法。

第一种是如上题hdu2196的写法,求出每个点的最远距离最后取最大值,这样不会增加太多的复杂度,因为每次dfs也都知识O(E)的复杂度。

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<vector>
 7 using namespace std;
 8 const int maxn = 40005;
 9 int f[maxn], g[maxn], h[maxn], longest[maxn];
10 vector<int> son[maxn], w[maxn];
11 
12 int dfs(int root, int pre){
13     int i, j;
14     int est = 0, esti=-1, er=0;
15     if(f[root]!=-1) return f[root];
16     if(son[root].empty()) return f[root] = 0;
17     for(i=0;i<son[root].size();i++){
18         if(pre!=son[root][i]){
19             if(dfs(son[root][i],root)+w[root][i]>est){
20                 est = f[son[root][i]]+w[root][i];
21                 esti = i;
22             }
23         }
24     }
25     longest[root] = esti;
26     for(i=0;i<son[root].size();i++){
27         if(pre!=son[root][i]){
28             if(f[son[root][i]]+w[root][i]>er&&i!=longest[root]){
29                 er = f[son[root][i]]+w[root][i];
30             }
31         }
32     }
33     g[root] = er;
34     return f[root] = est;
35 }
36 
37 void dfs1(int root, int pre){
38     int i, j;
39     for(i=0;i<son[root].size();i++){
40         if(pre!=son[root][i]){
41             if(i!=longest[root]){
42                 h[son[root][i]] = max(h[root],f[root])+w[root][i];
43             }
44             else{
45                 h[son[root][i]] = max(h[root],g[root])+w[root][i];
46             }
47             dfs1(son[root][i],root);
48         }
49     }
50 }
51 
52 void Init(int n){
53     int i;
54     for(i=0;i<=n;i++){
55         f[i] = g[i] = h[i] = longest[i] = -1;
56         son[i].clear();
57         w[i].clear();
58     }
59 }
60 int main(){
61     int i, j, k, n, m, ans;
62     int x1, x2, l;
63     char opt;
64     while(~scanf("%d%d",&n,&m)){
65         Init(n);
66         for(i=0;i<m;i++){
67             scanf("%d%d%d",&x1,&x2,&l);
68             scanf(" %c",&opt);
69             son[x1].push_back(x2);w[x1].push_back(l);
70             son[x2].push_back(x1);w[x2].push_back(l);
71         }
72         for(i=1;i<=n;i++){
73             if(f[i]==-1){
74                 f[i] = dfs(i,-1);
75                 h[i] = 0; dfs1(i,-1);
76             }
77         }
78         ans = 0;
79         for(i=1;i<=n;i++){
80             ans = max(ans,max(f[i],h[i]));
81         }
82         printf("%d\n",ans);
83     }
84     return 0;
85 }

第二种是利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点。这样就可以首先任取一个点,bfs求出离其最远的点,在用同样的方法求出离这个叶子节点最远的点,此时两点间的距离就是树的直径。

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<vector>
 7 #include<queue>
 8 using namespace std;
 9 const int maxn = 40005;
10 vector<int> son[maxn], w[maxn];
11 bool vis[maxn], viss[maxn];
12 int f[maxn];
13 int bfs(int root){
14     int i, j, k;
15     int ans = root, maxx = 0;
16     queue<int> q;
17     memset(vis,0,sizeof(vis));
18     memset(f,0,sizeof(f));
19     q.push(root);
20     vis[root] = 1;f[root] = 0;viss[root] = 1;
21     while(!q.empty()){
22         root = q.front();
23         q.pop();
24         for(i=0;i<son[root].size();i++){
25             if(vis[son[root][i]]==0){
26                 q.push(son[root][i]);
27                 vis[son[root][i]] = 1;viss[son[root][i]] = 1;
28                 f[son[root][i]] = f[root]+w[root][i];
29                 if(maxx<f[son[root][i]]){
30                     maxx = f[son[root][i]];
31                     ans = son[root][i];
32                 }
33             }
34         }
35     }
36     return ans;
37 }
38 int solve(int root){
39     int  u, v;
40     u = bfs(root);
41     v = bfs(u);
42     return f[v];
43 }
44 int main(){
45     int i, j, k, n, m;
46     int x1, x2, l, u;
47     int res;
48     char opt;
49     while(~scanf("%d%d",&n,&m)){
50         for(i=0;i<=n;i++){
51             son[i].clear();
52             w[i].clear();
53         }
54         for(i=0;i<m;i++){
55             scanf("%d%d%d",&x1,&x2,&l);
56             scanf(" %c",&opt);
57             son[x1].push_back(x2);w[x1].push_back(l);
58             son[x2].push_back(x1);w[x2].push_back(l);
59         }
60         res = 0;
61         memset(viss,0,sizeof(vis));
62         for(i=1;i<=n;i++){
63             if(viss[i]==0){
64                 res = max(res,solve(i));
65             }
66         }
67         printf("%d\n",res);
68     }
69     return 0;
70 }

ps:搜索也可以用dfs的方法搜,不过个人觉得bfs虽然更长,但比较好写,不容易出错。

第三种方法应该也可以算是树的直径的一个性质了吧,树的直径的长度一定会是某个点的最长距离f[i]与次长距离g[i]之和。最后求出max{f[i]+g[i]}就可以了,用到方法1中的第一个dfs就行了

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<vector>
 7 using namespace std;
 8 const int maxn = 40005;
 9 int f[maxn], g[maxn], longest[maxn];
10 vector<int> son[maxn], w[maxn];
11 int dfs(int root, int pre){
12     int i, j;
13     int est = 0, esti=-1, er=0;
14     if(f[root]!=-1) return f[root];
15     if(son[root].empty()) return f[root] = 0;
16     for(i=0;i<son[root].size();i++){
17         if(pre!=son[root][i]){
18             if(dfs(son[root][i],root)+w[root][i]>est){
19                 est = f[son[root][i]]+w[root][i];
20                 esti = i;
21             }
22         }
23     }
24     longest[root] = esti;
25     for(i=0;i<son[root].size();i++){
26         if(pre!=son[root][i]){
27             if(f[son[root][i]]+w[root][i]>er&&i!=longest[root]){
28                 er = f[son[root][i]]+w[root][i];
29             }
30         }
31     }
32     g[root] = er;
33     return f[root] = est;
34 }
35 
36 void Init(int n){
37     int i;
38     for(i=0;i<=n;i++){
39         f[i] = g[i] = longest[i] = -1;
40         son[i].clear();
41         w[i].clear();
42     }
43 }
44 int main(){
45     int i, j, k, n, m, ans;
46     int x1, x2, l;
47     char opt;
48     while(~scanf("%d%d",&n,&m)){
49         Init(n);
50         for(i=0;i<m;i++){
51             scanf("%d%d%d",&x1,&x2,&l);
52             scanf(" %c",&opt);
53             son[x1].push_back(x2);w[x1].push_back(l);
54             son[x2].push_back(x1);w[x2].push_back(l);
55         }
56         for(i=1;i<=n;i++){
57             if(f[i]==-1){
58                 f[i] = dfs(i,-1);
59             }
60         }
61         ans = 0;
62         for(i=1;i<=n;i++){
63             ans = max(ans,f[i]+g[i]);
64         }
65         printf("%d\n",ans);
66     }
67     return 0;
68 }

树的直径应该就是以上几种方法了吧,不过从poj1985的三种方法可以得出用搜索的方法求某个点的最远的点的距离了,就是先对任意一个点求距离其最远的顶点,最后可以得到一条树的直径的两个端点,以这两个端点开始去遍历整棵树,两个端点到每个点的距离较大值就会是这个点在树上能够走的最远距离。手画了几个sample,觉得如果树有多条直径,这个结论也应该是正确的。

转载于:https://www.cnblogs.com/celia01/archive/2012/07/30/2615842.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/434377.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux sd卡 读写速度测试_铠侠(原东芝存储)SD卡,大容量存储时代,高速读写选择...

作为一个经常出去旅行的旅游博主&#xff0c;在旅行过程中&#xff0c;还是有很多拍摄的需求。无论是存储美图&#xff0c;还是视频&#xff0c;一个大容量、安全可靠的储存卡还是很有必要的。这既可以缓解因为容量不够&#xff0c;频繁导数据的尴尬。又不会因为数据丢失&#…

potplayer 多个进程_操作系统 | 进程同步与进程互斥

主题 进程同步与进程互斥 01进程同步 问题在多道批处理系统中&#xff0c;多个进程是并发执行的&#xff0c;而并发执行的进程具有异步性&#xff0c;也就是说&#xff0c;各个进程以各自独立的、不可预知的速度向前推进。这样会带来什么问题呢&#xff1f;如果有 AB…

Java中间件:淘宝网系统高性能利器

【TechTarget中国原创】淘宝网是亚太最大的网络零售商圈&#xff0c;其知名度毋庸置疑&#xff0c;吸引着越来越多的消费者从街头移步这里&#xff0c;成为其忠实粉丝。如此多的用户和交易量&#xff0c;也意味着海量的信息处理&#xff0c;其背后的IT架构的稳定性、可靠性也显…

@autowired注解 抽象类_别再用ifelse了,用注解去代替他吧

来自公众号&#xff1a;咖啡拿铁策略模式经常在网上看到一些名为“别再if-else走天下了”&#xff0c;“教你干掉if-else”等之类的文章&#xff0c;大部分都会讲到用策略模式去代替if-else。策略模式实现的方式也大同小异。主要是定义统一行为(接口或抽象类)&#xff0c;并实现…

卸载mysql8.0卸载程序_程序卸载失败,来使用微软官方的Windows卸载工具试试

在我们实际的Windows操作系统使用中&#xff0c;总会遇到一些程序无法成功卸载的情况。当然&#xff0c;我们可以使用第三方软件来进行尝试卸载。要么&#xff0c;第三方软件会进行收费。要么&#xff0c;免费的会带给你捆绑软件的安装或者烦人的广告。还可能会造成系统文件的误…

英特网rst服务器未在运行,技术员示范win7系统提示“英特尔(R)RST服务未在运行”的详细办法...

不知道大家有没有遇到过win7系统提示“英特尔(R)RST服务未在运行”的问题&#xff0c;最近有很多朋友来向我咨询win7系统提示“英特尔(R)RST服务未在运行”的问题如何解决&#xff0c;于是小编就个大家整理的win7系统提示“英特尔(R)RST服务未在运行”的解决步骤&#xff0c;就…

小米手机电池恢复代码_解决小米手机屏幕问题的方法

屏幕在我们的小米手机中永远不会失败&#xff0c;因为没有它&#xff0c;我们将无法使用可用的应用程序和功能。为了帮助大家&#xff0c;我们汇总了小米和Redmi手机中最常见的问题&#xff0c;为您提供了针对我们所面临的每种情况的解决方案。MIUI定制层汇集了适用于小米手机的…

【原】winform高效导出Excel带格式设置

参考网上的方法修改&#xff0c;1000条记录导出只要3S&#xff08;1GRDM,C2.8CPU&#xff09;.1.项目添加excel对象类库的引用&#xff0c;Microsoft Excel 11.0 object library&#xff08;不同版本的Excel&#xff0c;类库不同&#xff0c;这是2003的&#xff09; 2.代码1//-…

vscode 逗号不换行_来自一个插件的疯狂夸赞,VS Code「彩虹屁」插件问世,网友:我想要郭德纲版...

听说有人开发了「虚拟程序员鼓励师」&#xff0c;安装使用后的我疯狂捶墙&#xff0c;导致我家变成了单间。机器之心报道&#xff0c;机器之心编辑部。你可能从未想过&#xff0c;会有这么一个人&#xff1a;对你写的每一行代码都不吝夸赞&#xff0c;知道你什么时候想骂人&…

电压源和电流的关联参考方向_结点电压法解题系列之四:电流源支路

利用结点电压法求解时&#xff0c;有的结点之间连接的是电流源支路。如图1所示电路中&#xff0c;结点2与参考结点4之间连接的是5A电流源。对结点2列写标准形式KCL&#xff0c;或直接利用KCL列出结点电压方程&#xff0c;都很容易&#xff0c;也不易出错。只需要注意&#xff1…

狼人杀服务器紧急维护中,狼人杀最可怕的武器是那张嘴?禁言长老:你已被管理员禁言一天!...

语言的能力有多强&#xff1f;不论是用来攻击对手&#xff0c;或是讨好他人&#xff0c;讽刺或是欺骗&#xff0c;语言有着神秘的力量&#xff0c;仿佛能够颠倒黑白。对于那些"口吐芬芳"的人&#xff0c;更是恨不得在他嘴上贴个封条&#xff0c;让他好好安静一会。相…

炎炎夏日需要一个清凉的地 - 自制水冷系统(十一 指尖的思绪之程序篇)

前段时间接手了一个项目&#xff0c;所以DIY的进程有些停滞。实际编写的程序并没有多长时间&#xff0c;得益于Keil这个强大的IDE。能在第一次做51开发的时候&#xff0c;如此顺利的完成代码。不多说废话了&#xff0c;说明下代码的具体思路。具体思路根据&#xff08;八 系统设…

wordpress 后台慢_建站经验-wordpress用户注册收不到验证邮件

背景我的一个博客http://axuretop.com&#xff0c;已经在后台开放注册了&#xff0c;注册用户默认为“订阅者”。一旦发布新的文章&#xff0c;会订阅邮件给用户。后台有300多个订阅用户&#xff0c;但是发现评论文章的很少&#xff0c;严重怀疑他们无法订阅我的文章&#xff0…

ai字体行间距怎么调整_字体基础知识(一)

本期教程主要讲解字体基础知识&#xff1a;字体、字号、字形、字重、行高、行距、字间距、字偶间距。本文所用软件为Microsoft PowerPoint 2013。1 字体文字的风格样式&#xff0c;就是我们平时常说的黑体、宋体、楷体、Segoe UI Black、Courier New、Consolas。如下图所示&…

免费的crm系统部署在自己的服务器,crm系统本地部署与云端部署的区别

CRM系统的部署方式通常有三种模式&#xff0c;分别是&#xff1a;本地部署、云端部署、公有云部署等三种模式。通常企业在选择的部署方式是本地部署与云端部署。那么他们部署方式得区别是什么?本地部署CRM系统本地部署的CRM软件&#xff1a;是意味着保存在企业自身的服务器中。…

gitee怎么仓库间传文件_实现一个简单的基于码云(Gitee) 的 Storage

实现一个简单的基于码云(Gitee) 的 StorageIntro上次在 asp.net core 从单机到集群 一文中提到存储还不支持分布式&#xff0c;并立了一个 flag基于 github 或者 开源中国的码云实现一个 storage于是这两天就来填坑了。。实现了一个简单的基于开源中国的码云的 storage准备工作…

载波聚合或双连接的方式进行_智能电表常用远程抄表方式,您想知道吗?--老兵聊电之...

智能电表的远程抄表方式有多种方式&#xff0c;但老王更喜欢以下几种抄表方式&#xff0c;希望您能接受。一、智能电表的工作原理1.智能电表主要是由电子元器件构成&#xff0c;其工作原理是先通过对用户供电电压和电流的实时采样&#xff0c;再采用专用的电能表集成电路&#…

搞个服务器安装黑群晖系统,牛人闲置电脑大改造!超低成本组建家用黑群晖NAS...

一、前言&#xff1a;大家好&#xff0c;俺又来了。这篇原创很早就在构思怎么写了&#xff0c;因为确实作为一个数码爱好者来说&#xff0c;当得知有 群晖 威联通 这种NAS 的东西存在的时候&#xff0c;就忍不住想体验体验。但是奈何自己的资金不够&#xff0c;想一想&#xff…

立体旋转查看图片

声明&#xff1a;如果程序有问题&#xff0c;请各位大虾多多指点&#xff0c;谢谢。 基于psoft.js制作的一款立体旋转查看图片应用 1.可以通过鼠标滑动来操作图片的旋转&#xff0c;可以向右&#xff0c;向左拖动 a。向左滑动 b。向右滑动 c。向左转到一下 2.代码实现&#xff…

asterisk架构

从架构的角度看来&#xff0c;Asterisk是由许多不同的模块组成的。在设计基于Asterisk的系统时&#xff0c;这种模块化的特性&#xff0c;提供了几乎无限的灵活必。作为Asterisk系统管理员&#xff0c;你拥有选择加载模块的权利。你所加载的每一个模块&#xff0c;都提供了不同…