[正经分析] DAG上dp两种做法的区别——拓扑序与SPFA
在下最近刷了几道DAG图上dp的题目。
要提到的第一道是NOIP原题《最优贸易》。这是一个缩点后带点权的DAG上dp,它同时规定了起点和终点。
第二道是洛谷上的NOI导刊题目《最长路》,一个裸的DAG上dp,也同时规定了起点和终点。
对于这两道题目,我分别用了两种不同的方法来写。
第一道题目,我建立了一个反向图,从起点和终点分别用两张图来进行Floodfill,若某个点不能被两遍Floodfill遍历到,则这个点是无用点,应当剔除。这样是为了方便后面作DAG上dp时,使用拓扑序来进行过程。
第二道题目,我直接用了spfa,把松弛的条件的小于号改成大于号。
而后我才发现,第一题也可以用spfa写。
这是为什么?
我想了一下。首先spfa跑最长路,它得保证是一张DAG。否则你可以在一个正权环上无限的松弛下去。
其次考虑一下最长路的DAG拓扑序dp做法。
是不是一个点,能够更新它的状态的点的状态全部被确定了,它的状态才能够被确定?
然而SPFA并不是这么做的。因为类似BFS过程的缘故,可能一条路径已经早就更新了这个点的状态,而另一条能松弛它的路径还没能更新它的点状态。
这样子得到的结果会是错误的吗?并不会。 SPFA有效的避免了错解情况的发生。
讨论以下情况:
a->b 路径A:中间有几个点 路径B:中间有十几个点。
b->c 只有一条路径。
a的入度为0。
DAG-dp情况:
首先从a开始拓扑序dp。显然a->b 路径上的所有点的状态确定下来后,b的状态被确定,随后b->c的状态一个个地被确定。
SPFA情况:
由于BFS缘故,路径A上的点首先被确定状态。随后b->c依次被更新状态,但是路径B能得到更优的答案。
随后,路径B跟上来了。它更新了b的状态,b随后再次被放入处理队列中,依次而来的,b->c上面的点一个个地再次重新入队,再次被更新状态。
因此,使用SPFA进行类似最长路的DAG上dp时,每个点的最终状态跟拓扑序dp一样,会是最优的。这就是为什么SPFA能跑DAGdp的原因。
什么时候使用SPFA跑DAG会更好呢?确定了起点和终点的状况下。 如我原先所用的方法,我做了两遍FloodFill,又删了一遍点,还要作各种判断,才能避免其它点对拓扑序dp的干扰。但是使用SPFA,从起点开始松弛,直接松弛到终点的最优状态,它有效的兼顾了DAGdp所应该得到的最优状态,而又避免了拓扑序更新状态的条件之一——入度必须为0.因为这么做,显然会受到其它多余点(起点不能到的点/不能到终点的点)的干扰。
两者的复杂度如何呢?如果不考虑起点和终点的条件,拓扑序肯定更优。但如果考虑起点和终点的条件,综合考虑代码复杂度和时间复杂度,我觉得我应该会写SPFA。
感觉值得做个记录....qwq
UPD
有时候是可以不用排除多余点的。
也就是说,只用给起点设置初始状态,其它的状态全部不设
那么作拓扑排序得到的结果也应该与排除多余点等价
大部分题目应该都是如此。
[正经分析] DAG上dp两种做法的区别——拓扑序与SPFA的更多相关文章
- DAG上dp思想
DAG上DP的思想 在下最近刷了几道DAG图上dp的题目.要提到的第一道是NOIP原题<最优贸易>.这是一个缩点后带点权的DAG上dp,它同时规定了起点和终点.第二道是洛谷上的NOI导刊题 ...
- jqGrid中实现radiobutton的两种做法
http://blog.sina.com.cn/s/blog_4f925fc30102e27j.html jqGrid中实现radiobutton的两种做法 ------------------- ...
- SqlServer保留几位小数的两种做法
SqlServer保留几位小数的两种做法 数据库里的 float momey 类型,都会精确到多位小数.但有时候 我们不需要那么精确,例如,只精确到两位有效数字. 解决: 1. 使用 Round( ...
- 软件公司的两种管理方式 总体来说,这个世界上存在两种不同的软件公司的组织结构。我把他们叫做 Widget Factory(小商品工厂) 和 Film Crews(电影工作组
软件公司的两种管理方式 一个简单的回答应该是——“因为在我们的社会里,我们总是会认为薪水和会和职位的层次绑在一起”.但是,这个答案同时也折射出一个事实——我们的薪资是基于我们的所理解的价值,但这并没有 ...
- bzoj1093: [ZJOI2007]最大半连通子图 scc缩点+dag上dp
一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V ...
- ACE_linux:Reactor与Proactor两种模式的区别
一.概念: Reactor与Proactor两种模式的区别.这里我们只关注read操作,因为write操作也是差不多的.下面是Reactor的做法: 某个事件处理器宣称它对某个socket上的读事件很 ...
- jsp中两种include的区别【转】
引用文章:http://www.ibm.com/developerworks/cn/java/j-jsp04293/ http://www.cnblogs.com/lazycoding/archive ...
- 什么是CS和BS结构,两种结构的区别
什么是CS和BS结构,两种结构的区别 什么是C/S和B/S结构? C/S又称Client/Server或客户/服务器模式.服务器通常采用高性能的PC.工作站或小型机,并采用大型数据库系 ...
- Ajax的get和post两种请求方式区别
Ajax的get和post两种请求方式区别 (摘录):http://ip-10000.blog.sohu.com/114437748.html 解get和post的区别. 1. get是把参数数据队列 ...
随机推荐
- Hadoop运维手记
1.处理hadoop的namenode宕机 处理措施:进入hadoop的bin目录,重启namenode服务 操作命令:cd path/to/hadoop/bin ./hadoop-daemon.sh ...
- Linux环境下如何配置IP地址、MAC地址
Linux环境下如何配置IP地址.MAC地址 1.配置IP地址 进入配置IP地址路径,进行修改即可 cd /etc/network vim interface 加入以下内容: iface eth0 i ...
- exception disappear when forgot to await an async method
https://github.com/aspnet/AspNetWebStack/issues/235 https://stackoverflow.com/questions/5383310/catc ...
- JS中innerHTML和innerText,outerHTML和outerText
innerHTML 声明了元素含有的HTML文本,不包括元素本身的开始标记和结束标记 innerHTML是符合W3C标准的属性,而innerText只适用于IE浏览器(现在也适应chrome浏览器 ...
- C++函数的返回值——返回引用类型&非引用类型
函数的返回主要分为以下几种情况: 1.主函数main的返回值: 允许主函数main没有返回值就可结束:可将主函数main返回的值视为状态指示器,返回0表示程序运行成功,其他大部分返回值则表示失败. 2 ...
- Windows__书
1.<<Windows 网络与通信程序设计>> (第2版) 2. 3.
- 基于Codis的Redis集群部署
Codis是基于代理的高性能Redis集群方案,使用Go语言进行开发,现在在在豌豆荚及其它公司内已经广泛使用,当然也包括我们公司. Codis与常见的Redis集群方案对比. 在搭建的时候,个人觉得R ...
- 雷林鹏分享:Ruby 范围(Range)
Ruby 范围(Range) 范围(Range)无处不在:January 到 December. 0 到 9.等等.Ruby 支持范围,并允许我们以不同的方式使用范围: 作为序列的范围 作为条件的范围 ...
- 雷林鹏分享:Ruby CGI Sessions
Ruby CGI Sessions CGI::Session 可以为用户和CGI环境保存持久的会话状态,会话使用后需要关闭,这样可以保证数据写入到存储当中,当会话完成后,你需要删除该数据. #!/us ...
- 手把手教你如何加入到github的开源世界
我曾经一直想加入到开源项目中,但是因为没有人指导流程,网上看了很多,基本都是说了个大概,如果你也是一个初出茅庐的人,那么,我将以自己提交的一次开源代码为例,教会你步入开源的世界. 1,首先登陆到htt ...