题意

在一个DAG上,从顶点1走到顶点n,路径上需要消费时间,求在限定时间内从1到n经过城市最多的一条路径

我的做法和题解差不多,不过最近可能看primer看多了,写得比较复杂和结构化

自己做了一些小优化。。然而貌似跑得更慢了

先定义dp[i][j], 表示到第i个城市,经过j个城市所花的时间

然后转移方程比较好写,就是对于能到达i的点v

dp[i][j] = min(dp[i][j], dp[v][j-1] + e.cost)  e是(i, v)这条边

因为要输出路径,所以还要有一个记录路径的数组,伴随dp[i][j]的更新而更新

如果v能更新i,那么p[i][j] = v,这样就可以记录路径了

(在结构体里dp[i][j]是N_T, p[i][j] 是N_N)

然后我仔细一想。。如果这么写转移会有很多多余的情况

于是作死加了很多不必要的优化,我保存了那些非0的数值,记录在一个队列里,然后再用map映射一下

不过好像没什么效果

还有一点就是dp的时候要按照拓扑序来更新

我把求拓扑序和dp的过程分开了,其实也可以合并在一起(分开好蠢啊)

最后动态清了下内存,才卡着内存勉强过了

PS用题解学英语orzzz

vertice 顶点
acyclic 非循环的
recursive 递归
iterate 迭代

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
#include <queue>
#include <map>
using namespace std;
const int Maxn = ;
int n, m, T;
struct Edge
{
int front, to, t;
};
vector <Edge> edges;
vector <short int> G[Maxn];
short int R[Maxn];
bool flag[Maxn];
queue<short int> Tp;
void AddEdge(int u, int v, int tt)
{
edges.push_back((Edge){u, v, tt});
R[v]++;
G[u].push_back(edges.size()-);
} struct dp
{
int N_T[Maxn], D;
vector<int> Q;
map<short int, short int> f, N_N;
dp()
{
f.clear(); N_N.clear(); Q.clear();
}
void update(dp B, int t)
{
for(int i = ; i < B.Q.size(); i++)
{
int k = B.Q[i];
if(f[k+])
{
if(N_T[k+] > B.N_T[k] + t)
{
N_T[k+] = B.N_T[k] + t;
N_N[k+] = B.D;
}
}else
{
if(B.N_T[k] + t > T) continue;
N_T[k+] = B.N_T[k] + t;
N_N[k+] = B.D;
f[k+] = true;
Q.push_back(k+);
}
}
}
void clear()
{
Q.clear(); f.clear();
}
}Dp[Maxn];
int main()
{
//freopen("a.txt", "r", stdin);
memset(flag, , sizeof(flag));
memset(R, , sizeof(R));
int u, v, t;
cin>>n>>m>>T; for(int i = ; i < n; i++) G[i].clear(); edges.clear(); for(int i = ; i <= m; i++)
{
cin>>u>>v>>t;
AddEdge(u, v, t);
}
for(int k = ; k <= n; k++)
{
for(int i = ; i <= n; i++)
{
if(flag[i]) continue;
if(R[i] == )
{
for(int x = ; x < G[i].size(); x++)
R[edges[G[i][x]].to]--;
Tp.push(i); flag[i] = true;
break;
}
}
} Dp[].N_T[] = ; Dp[].Q.push_back();
for(int i = ; i <= n; i++) Dp[i].D = i; while(!Tp.empty())
{
int x = Tp.front(); Tp.pop();
for(int u = ; u < G[x].size(); u++)
{
Edge &e = edges[G[x][u]];
Dp[e.to].update(Dp[x], e.t);
}
if(x != n) Dp[x].clear();
} int Max = , x = n;
for(int i = ; i < Dp[n].Q.size(); i++) Max = ((Max < Dp[n].Q[i]) ? Dp[n].Q[i] : Max);
cout<<Max<<endl;
stack<short int> S;
while(x != )
{
S.push(x);
x = Dp[x].N_N[Max];
Max--;
}
printf("1 ");
while(!S.empty())
{
printf("%d ", S.top());
S.pop();
}
}

Codeforce 721C DP+DAG拓扑序的更多相关文章

  1. [正经分析] DAG上dp两种做法的区别——拓扑序与SPFA

    在下最近刷了几道DAG图上dp的题目. 要提到的第一道是NOIP原题<最优贸易>.这是一个缩点后带点权的DAG上dp,它同时规定了起点和终点. 第二道是洛谷上的NOI导刊题目<最长路 ...

  2. [NOIP2017]逛公园 最短路图 拓扑序DP

    ---题面--- 题解: 挺好的一道题. 首先我们将所有边反向,跑出n到每个点的最短路,然后f[i][j]表示从i号节点出发,路径长比最短路大j的方案数. 观察到,如果图中出现了0环,那么我们可以通过 ...

  3. 拓扑序+dp Codeforces Round #374 (Div. 2) C

    http://codeforces.com/contest/721/problem/C 题目大意:给你有向路,每条路都有一个权值t,你从1走到n,最多花费不能超过T,问在T时间内最多能访问多少城市? ...

  4. [十二省联考2019]字符串问题——后缀自动机+parent树优化建图+拓扑序DP+倍增

    题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的 ...

  5. bzoj5017 炸弹 (线段树优化建图+tarjan+拓扑序dp)

    直接建图边数太多,用线段树优化一下 然后缩点,记下来每个点里有多少个炸弹 然后按拓扑序反向dp一下就行了 #include<bits/stdc++.h> #define pa pair&l ...

  6. NOIP2017 逛公园 题解报告 【最短路 + 拓扑序 + dp】

    题目描述 策策同学特别喜欢逛公园.公园可以看成一张NNN个点MMM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,NNN号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花 ...

  7. Graph_Master(连通分量_H_Trajan+拓扑序dp)

    Graph_Master_连通分量_H 题目描述: 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条 ...

  8. [bzoj3887][Usaco2015 Jan]Grass Cownoisseur_trajan_拓扑排序_拓扑序dp

    [Usaco2015 Jan]Grass Cownoisseur 题目大意:给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在 ...

  9. [ZJOI2007]最大半连通子图(Tarjan,拓扑序DP)

    [ZJOI2007]最大半连通子图 题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v ...

随机推荐

  1. linux 查看系统当前时间,修改时间

    linux 查看系统当前时间,修改时间1. 查看时间和日期命令 : "date"2.设置时间和日期例如:将系统日期设定成2018年6月8日的命令命令 : "date -s ...

  2. 打造自己的JavaScript武器库(转)

    作者: SlaneYang https://segmentfault.com/a/1190000011966867 前言 作为战斗在业务一线的前端,要想少加班,就要想办法提高工作效率.这里提一个小点, ...

  3. laydate js动态添加时间

    $("#test2").click(function(){ var input=$('<input/>'); $("#test1").append( ...

  4. lnmp+phpmyadmin+laravel 环境配置

    腾讯云 Ubuntu16.04 添加用户 useradd 与 adduser Ubuntu下useradd不会在/home下自动创建与用户名同名的用户目录,而且不会自动选择shell版本,也没有设置密 ...

  5. Pig关系型运算符例子

    1.新建两个文件A.txt与B.txt, A.txt文件的内容如下: 0,1,2 1,3,4 B.txt文件的内容如下: 0,5,2 1,7,8 将这两个文件上传到目录/zwy/soft 2.定义关系 ...

  6. Python学习第二弹

    昨天补充: 编码: Unicode ; utf-8 ; GBK       关系:   关键字:1. continue 终止当前循环,进行下一次循环 2. break      终止循环 题6解法2: ...

  7. django的模型和基本的脚本命令

    python manage.py startproject project_name  创建一个django项目 python manage.py startapp app_name  创建一个app ...

  8. linux文件操作篇 (一)文件属性与权限

    文件的属性和权限是linux中 目录 和 文件 的两个基本特性. #属性: . 所有者属性 . 访问权限属性   -rwxrwxr-x #第一个字符是文件类别 -表示 普通文件 d 表示目录 b 表示 ...

  9. (数据科学学习手札01)Python与R基本数据结构之异同

    Python 1.列表(list) list1 = [i for i in range(10)] list1[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 特点:可遍历,可索引,可切片 ...

  10. 44- EF + Identity实现

    1-配置EF, 需要创建如下几个类 默认User主键为guid类型,现在改成int类型 namespace MvcCookieAuthSample.Models { public class Appl ...