洛谷P1137 旅行计划 解题报告(拓扑排序+DP)
我看了一下其他大佬的题解,大部分都是拓扑排序加上DP。那么我想有的人是不明白为什么这么做的,拓扑排序有什么性质使得可以DP呢?下面我就提一下。
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。 (源自百度)
通俗的说就是,一张有向无环图的拓扑序可以使得任意的起点u,它的一个终点v,在序列中的顺序是u在前v在后
我下面先附上代码,然后在继续说明
#include<bits/stdc++.h>
using namespace std; const int maxn=100000+15;
int n,m,sum,tot;
int head[maxn],ru[maxn],ts[maxn],dp[maxn];
struct EDGE
{
int to;int next;
}edge[maxn<<2];
void add(int x,int y)
{
edge[++sum].next=head[x];
edge[sum].to=y;
head[x]=sum;
}
void topsort()
{
queue <int> q;
for (int i=1;i<=n;i++)
if (ru[i]==0) {
q.push(i);
ts[++tot]=i;
}
while (!q.empty())
{
int u=q.front();q.pop();
for (int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
ru[v]--;
if (ru[v]==0) {
q.push(v);ts[++tot]=v;
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
ru[v]++;
}
topsort();
for (int i=1;i<=n;i++) dp[i]=1;
for (int i=1;i<=n;i++)
{
int u=ts[i];
for (int j=head[u];j;j=edge[j].next)
{
int v=edge[j].to;
dp[v]=max(dp[v],dp[u]+1);
}
}
for (int i=1;i<=n;i++)
printf("%d\n",dp[i]);
return 0;
}
仔细看DP部分,还记得DP需要满足什么原则吗?无后效性。如果不是在拓扑序中进行DP,会完全破坏无后效性(当然这也下面为什么有人用记忆化搜索的原因,记忆化搜索同样可以解决无后效性的问题)。正是因为拓扑序u在前,v在后的性质,这才选择使用拓扑排序,毕竟它的代码实现很轻松,而且运行时间也不差。
至于怎么求拓扑序,就是把入度为0(就是没有边把它作为终点)的点入队,并加入拓扑序。之后断掉以这个点为起点的边,即将这些边的终点的入度减一,直到队为空就好。
那么就是这些了,希望对大家有帮助
洛谷P1137 旅行计划 解题报告(拓扑排序+DP)的更多相关文章
- 洛谷P1137 旅行计划
P1137 旅行计划 题目描述 小明要去一个国家旅游.这个国家有N个城市,编号为1-N,并且有M条道路连接着,小明准备从其中一个城市出发,并只往东走到城市i停止. 所以他就需要选择最先到达的城市,并制 ...
- 洛谷 P1137 旅行计划 (拓扑排序+dp)
在DAG中,拓扑排序可以确定dp的顺序 把图的信息转化到一个拓扑序上 注意转移的时候要用边转移 这道题的dp是用刷表法 #include<bits/stdc++.h> #define RE ...
- 洛谷 P1137 旅行计划
旅行计划 待证明这样dp的正确性. #include <iostream> #include <cstdio> #include <cstring> #includ ...
- 洛谷——P1137 旅行计划
https://www.luogu.org/problem/show?pid=1137 题目描述 小明要去一个国家旅游.这个国家有N个城市,编号为1-N,并且有M条道路连接着,小明准备从其中一个城市出 ...
- 洛谷p1137旅行计划
题面 关于拓扑排序 因为这好几次考试的题目里都有在DAG中拓扑排序求最长/短路 txt说它非常的好用 就找了个题做了下 拓扑排序就是寻找图中所有的入度为零的点把他入队 然后再枚举它所有的连到的点,只要 ...
- 洛谷 P2680 运输计划 解题报告
P2680 运输计划 题目背景 公元2044年,人类进入了宇宙纪元. 题目描述 公元2044年,人类进入了宇宙纪元. \(L\)国有\(n\)个星球,还有\(n-1\)条双向航道,每条航道建立在两个星 ...
- 洛谷 P1783 海滩防御 解题报告
P1783 海滩防御 题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭 ...
- 洛谷 P4597 序列sequence 解题报告
P4597 序列sequence 题目背景 原题\(\tt{cf13c}\)数据加强版 题目描述 给定一个序列,每次操作可以把某个数\(+1\)或\(-1\).要求把序列变成非降数列.而且要求修改后的 ...
- 洛谷1087 FBI树 解题报告
洛谷1087 FBI树 本题地址:http://www.luogu.org/problem/show?pid=1087 题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全 ...
随机推荐
- vue2 router中的 @ 符号表示src
vue2 router中的 @ 符号表示src 学习了:https://segmentfault.com/q/1010000009549802 这个是webpack起的别名: 在build/webpa ...
- 指尖上的电商---(5)schema.xml配置具体解释
这一节我们看下schema.xml文件中各个节点的配置极其作用.schema.xml文件中面主要定义了索引数据类型,索引字段等信息. 主要包含了下面节点 1.fieldtype节点 fieldtype ...
- UE4在VS2013中各个编译配置代表意义
UE4中有个各式各样的编译配置,都怎么个意思呢? 对原文的理解和翻译. https://docs.unrealengine.com/latest/INT/Programming/Development ...
- 公布自己的pods到CocoaPods trunk 及问题记录
这两天准备把之前写的一些小玩意加入到pods库中去,參考了一些资料后进行操作,实际中也遇到了一些问题,记录下来.问题及解决方案在后面. 參考内容转载例如以下: 首先更新了用trunk之后,CocoaP ...
- pjlib深入剖析和使用详解
1. PJSIP简介 PJSIP的实现是为了能在嵌入式设备上高效实现SIP/VOIP.其主要特征包括: 1).极具移植性.(Extremely portable) ...
- 判断一个整数是否是回文数C++实现 leetcode系列(九)
判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 示例 1: 输入: 121 输出: true 示例 2: 输入: -121 输出: false 解释: 从左向 ...
- gcd的queue与group
queue相当于事件处理机制里的事件池:只是任务池: 线程作为事件处理的实施者,由线程池从任务池中获取任务进行调度派发: group相当与工作组,按照任务的相关性对任务进行组织.
- SpringCloud学习笔记(3)----Spring Cloud Netflix之深入理解Eureka
1. Eureka服务端的启动过程 1.1 入口类EurekaServerInitializerConfiguration类, public void start() { (new Thread(n ...
- NOIp模拟赛二十九
又是受虐的一天呢~接下来四天都要打模拟赛QAQ 今日分数:0(100)+100+0=100 A题O(读入)结论题判断结果时没return 0被subtask卡成0分,喜提fstQAQ,B题DP,C题不 ...
- Manacher笔记
(其实还是回文自动机好用,毛子真是牛逼) Manacher #include<iostream> #include<cstring> #include<cstdio> ...