洛谷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串,全 ...
随机推荐
- C++ STL 源代码学习(之deque篇)
stl_deque.h /** Class invariants: * For any nonsingular iterator i: * i.node is the address of an el ...
- HDU5638 / BestCoder Round #74 (div.1) 1003 Toposort 线段树+拓扑排序
Toposort 问题描述 给出nn个点mm条边的有向无环图. 要求删掉恰好kk条边使得字典序最小的拓扑序列尽可能小. 输入描述 输入包含多组数据. 第一行有一个整数TT, 表示测试数据组数. 对 ...
- kibana智能检索发送多次_msearch —— 配置index pattern,同时设置时间段,就知道到底是在哪些索引里去查找数据了
kibanasite/elasticsearch/log-*/_field_stats?level=indices 返回: {"_shards":{"total ...
- luogu 2679 子串
子串 史上最简短的一篇博客,毕竟看题解ac心疼我的kmp /* f[i][j][k][0/1]表示A的前i个,B的前j个,用到了k个子串,当前字符选或者不选. 所以f[0][0][0][0]的方案数为 ...
- ajax的cache缓存的使用方法
ajax中cache缓存的使用: 问题描述: 在IE.360浏览器上提交表单后,保存后的内容不回显(依然显示空或者之前的内容). 原因: 回显内容是使用ajax的get方式的请求查询数据,ajax的c ...
- LeetCode 437. Path Sum III (STL map前缀和)
找遍所有路径,特判以根为起点的串即可. 代码: /** * Definition for a binary tree node. * struct TreeNode { * int val; * Tr ...
- 【算法】单源最短路径和任意两点最短路径总结(补增:SPFA)
[Bellman-Ford算法] [算法]Bellman-Ford算法(单源最短路径问题)(判断负圈) 结构: #define MAX_V 10000 #define MAX_E 50000 int ...
- JavaScript学习——表格的隔行换色+高亮显示
1.案例一:我们希望在后台页面中实现一个隔行换色的效果显示所有的用户信息,显示效果如下: 1)新标签 <thead> //表头 <tr> <th></th&g ...
- 【转载】Reactor模式和NIO
当前分布式计算 Web Services盛行天下,这些网络服务的底层都离不开对socket的操作.他们都有一个共同的结构:1. Read request2. Decode request3. Proc ...
- hiho160周 - 字符串压缩,经典dp
题目链接 小Hi希望压缩一个只包含大写字母'A'-'Z'的字符串.他使用的方法是:如果某个子串 S 连续出现了 X 次,就用'X(S)'来表示.例如AAAAAAAAAABABABCCD可以用10(A) ...