旅行计划-DAG上最长路

http://www.luogu.org/problem/show?pid=1137

题目描述

小明要去一个国家旅游。这个国家有N个城市,编号为1~N,并且有M条道路连接着,小明准备从其中一个城市出发,并只往东走到城市i停止。

所以他就需要选择最先到达的城市,并制定一条路线以城市i为终点,使得线路上除了第一个城市,每个城市都在路线前一个城市东面,并且满足这个前提下还希望游览的城市尽量多。

现在,你只知道每一条道路所连接的两个城市的相对位置关系,但并不知道所有城市具体的位置。现在对于所有的i,都需要你为小明制定一条路线,并求出以城市i为终点最多能够游览多少个城市。

输入输出格式

输入格式:

输入的第1行为两个正整数N, M。

接下来M行,每行两个正整数x, y,表示了有一条连接城市x与城市y的道路,保证了城市x在城市y西面。

输出格式:

输出包括N行,第i行包含一个正整数,表示以第i个城市为终点最多能游览多少个城市。

Water....ORZ

 1 #include<iostream>
 2 #include<vector>
 3 #include<cstdio>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn=100000+10;
 7 const int inf=1<<30;
 8 vector<int> sons[maxn];
 9 int n,m,mem[maxn],v[maxn];
10 int dp(int x){
11     if(v[x]) return mem[x];
12     v[x]=1;
13     int& ans=mem[x];
14     ans=-inf;
15     if(sons[x].size()==0) return ans=1;
16     for(int i=0;i<sons[x].size();i++)
17         ans=max(ans,dp(sons[x][i])+1);
18     return ans;
19 }
20 int main()
21 {
22     memset(v,0,sizeof(v));
23     int a,b;
24     scanf("%d %d",&n,&m);
25     for(int i=1;i<=m;i++){
26         scanf("%d %d",&a,&b);
27         sons[b].push_back(a);
28     }
29     for(int i=1;i<=n;i++) cout<<dp(i)<<endl;
30     return 0;
31 }
时间: 2024-10-01 22:00:34

旅行计划-DAG上最长路的相关文章

UVA 10029 Edit Step Ladders ——(DAG求最长路)

题意:升序的给出一本若干个单词,每个单词都可删除一个字母,添加一个字母或者改变一个字母,如果任意一个操作以后能变成另外一个字典中的单词,那么就连一条有向边,求最长的长度. 分析:DAG的最长路和最短路在算法竞赛入门里边原原本本有的,结果我现在忘记了,,真是太弱了..方法就是,用map对应键值(以建图),然后删除操作和修改操作可以看做同一个操作,之后每个操作都是在相应的位置添加一个 '*' 就可以了.想说的有两点,一个是为什么删除和修改可以看做一个操作,其实删除这个操作根本就是多余的,因为一个单词

EOJ Monthly 2019.2 E 中位数 (二分+中位数+dag上dp)

题意: 一张由 n 个点,m 条边构成的有向无环图.每个点有点权 Ai.QQ 小方想知道所有起点为 1 ,终点为 n 的路径中最大的中位数是多少. 一条路径的中位数指的是:一条路径有 n 个点,将这 n 个点的权值从小到大排序后,排在位置 ⌊n2⌋+1 上的权值. 思路(官方题解): 考虑二分答案,我们需要验证路径最大的中位数是否 ≥mid . 我们把所有的点权做 −1/1 变换,即 ≥mid 的点权变为 1 ,否则变为 −1 . 根据题面路径中位数的定义,我们可以发现,如果这条路径的中位数 ≥

NYOJ_矩形嵌套(DAG上的最长路 + 经典dp)

本题大意:给定多个矩形的长和宽,让你判断最多能有几个矩形可以嵌套在一起,嵌套的条件为长和宽分别都小于另一个矩形的长和宽. 本题思路:其实这道题和之前做过的一道模版题数字三角形很相似,大体思路都一致,这道题是很经典的DAG上的最长路问题,用dp[ i ]表示以i为出发点的最长路的长度,因为每一步都只能走向他的相邻点,则 d[ i ]  = max(d[ j ] + 1)这里 j 是任意一个面积比 i 小的举行的编号. 下面的代码中附带了最小字典序最长路打印的问题,我们找到第一个路径最长的 i,往后

uva103(最长递增序列,dag上的最长路)

题目的意思是给定k个盒子,每个盒子的维度有n dimension 问最多有多少个盒子能够依次嵌套 但是这个嵌套的规则有点特殊,两个盒子,D = (d1,d2,...dn) ,E = (e1,e2...en) 只要盒子D的任意全排列,小于盒子E,那么就说明 盒子D能放入盒子E中,其实就是将两个盒子的维度排序,如果前一个盒子的维度依次小于后一个盒子,那么就说明前一个盒子能放入后一个盒子中 这个题目能够转化为最长递增子序列. 首先将盒子的维度从小到大排序,然后将k个盒子,按照排序后的第一维度从小到大排

POJ 1949 Chores(DAG上的最长路 , DP)

题意: 给定n项任务, 每项任务的完成用时t和完成每项任务前需要的k项任务, 求把所有任务完成的最短时间,有当前时间多项任务都可完成, 那么可以同时进行. 分析: 这题关键就是每项任务都会有先决条件, 要完成该项任务a必须先完成他的先决条件. 所以对于每个先决条件, 我们构建一条有向边到任务本身, 然后因为要求一个最小值, 按照最长路的方式松弛(dis[v] >= dis[u] + d, u是v的先决条件, d是v的完成时间,我们以边的终点完成时间作为边的权), 遇到没有出度的边记录答案. 方法

UVA 11324 The Largest Clique (强连通缩点 + DAG最长路)

链接 : http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=30726 题意 : 有向图G,求一个最大的点集,使得点集中任意两个节点u和v,满足 要么u可以到达v,要么v可以到达u,或者u和v可以相互到达. 可以强连通缩点成一张DAG,以为每个强连通分量要么选要么不选.求DAG上的最长路 二次建图 用了2种不同的方法,也分别用了记忆花搜索DP和直接递推DP vector建图和记忆化搜索: #include <algorithm

简单Dp----最长公共子序列,DAG最长路,简单区间DP等

/* uva 111 * 题意: * 顺序有变化的最长公共子序列: * 模板: */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int a[100]; int mu[100]; int Dp[100][100]; int main() { int n,x; scanf("%d", &n

HDU 3249 Test for job (有向无环图上的最长路,DP)

 解题思路: 求有向无环图上的最长路,简单的动态规划 #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include <cmath> #define LL long long using namespace std; const int

【强联通分量缩点】【最长路】【spfa】CH Round #59 - OrzCC杯NOIP模拟赛day1 队爷的讲学计划

10分算法:对于城市网络为一条单向链的数据, 20分算法:对于n<=20的数据,暴力搜出所有的可能路径. 结合以上可以得到30分. 60分算法:分析题意可得使者会带着去的城市也就是这个城市所在强联通分量的其他城市,这个过程的代价也就是这个强联通分量的城市数-1,且他可以选择任何一个其中的城市离开这个强联通分量.于是我们求出所有强联通分量,记录下每一个包含的城市数,然后缩点.接下来再用dfs,由于数据是构造的,只能得到60分. 100分算法:在缩点之后,这个图变成了一个有向无环图,我们将一条边连向