洛谷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串,全 ...
随机推荐
- HDU 1023
卡特兰数.把进栈看成是+1,出栈看成是-1,任何时候部分和都有a1+a2+....ak>=0.求这样的数列的个数.这明显是卡特兰数的一个解释嘛.在<组合数学>这本书就有这样的原本的证 ...
- uva725_一道水题(优化到了29ms)
//////////////////////////////////////////////////////////////////////////////////////////////////// ...
- java-集合类(二)
使用场景 1.多线程 (1)在jdk1.5之前原始的集合类中,仅仅有vector.stack.hashtable.enumeration等是线程安全的,其它的都是非线程安全的. 非线程安全的集合在多线 ...
- nyoj--214--单调递增子序列(二)(二分查找+LIS)
单调递增子序列(二) 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序 ...
- 获取新浪微博的Access_token
最近想爬取新浪微博的评论,百度了一下,有个新浪开放平台提供了这个API 于是按照它的说明,去获取Access_token: 1.点击微链接 2.立即创建微链接 3.选择网页应用 4.填写信息后提交 5 ...
- 1、Windows服务器 VS Linux服务器
- ZBrush雕刻生物小技巧
本教程主要学习如何使用ZBrush®3D图形绘制软件的工具和笔刷雕刻酷酷的生物造型,我们今天来看看在游戏.媒体和电视领域有着十几年丰富经验的3D角色艺术家Francis-Xavier Martins是 ...
- MyBatis中抽象方法中多个参数的问题
在使用MyBatis时,接口中的抽象方法只允许有1个参数,如果有多个参数,例如: Integer updatePassword( Integer id, String ...
- PKI和加密,散列算法
Day 11-PKI和加密,散列算法 PKI(Public Key Infrastructure公钥基础设施) 1 PKI(Public Key Infrastructure公钥基础设施)回顾学习 - ...
- BZOJ 2287 【POJ Challenge】消失之物(DP+容斥)
2287: [POJ Challenge]消失之物 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 986 Solved: 572[Submit][S ...