Codeforce 721C DP+DAG拓扑序
题意
在一个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拓扑序的更多相关文章
- [正经分析] DAG上dp两种做法的区别——拓扑序与SPFA
在下最近刷了几道DAG图上dp的题目. 要提到的第一道是NOIP原题<最优贸易>.这是一个缩点后带点权的DAG上dp,它同时规定了起点和终点. 第二道是洛谷上的NOI导刊题目<最长路 ...
- [NOIP2017]逛公园 最短路图 拓扑序DP
---题面--- 题解: 挺好的一道题. 首先我们将所有边反向,跑出n到每个点的最短路,然后f[i][j]表示从i号节点出发,路径长比最短路大j的方案数. 观察到,如果图中出现了0环,那么我们可以通过 ...
- 拓扑序+dp Codeforces Round #374 (Div. 2) C
http://codeforces.com/contest/721/problem/C 题目大意:给你有向路,每条路都有一个权值t,你从1走到n,最多花费不能超过T,问在T时间内最多能访问多少城市? ...
- [十二省联考2019]字符串问题——后缀自动机+parent树优化建图+拓扑序DP+倍增
题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的 ...
- bzoj5017 炸弹 (线段树优化建图+tarjan+拓扑序dp)
直接建图边数太多,用线段树优化一下 然后缩点,记下来每个点里有多少个炸弹 然后按拓扑序反向dp一下就行了 #include<bits/stdc++.h> #define pa pair&l ...
- NOIP2017 逛公园 题解报告 【最短路 + 拓扑序 + dp】
题目描述 策策同学特别喜欢逛公园.公园可以看成一张NNN个点MMM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,NNN号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花 ...
- Graph_Master(连通分量_H_Trajan+拓扑序dp)
Graph_Master_连通分量_H 题目描述: 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条 ...
- [bzoj3887][Usaco2015 Jan]Grass Cownoisseur_trajan_拓扑排序_拓扑序dp
[Usaco2015 Jan]Grass Cownoisseur 题目大意:给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在 ...
- [ZJOI2007]最大半连通子图(Tarjan,拓扑序DP)
[ZJOI2007]最大半连通子图 题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v ...
随机推荐
- VMware下CentOS7安装后,还原虚拟网络后,敲ifconfig不显示局域网ip解决方法
VMware下CentOS7安装后,还原虚拟网络后,敲ifconfig不显示局域网ip,没有出现eth0网卡,不能上网,SSH不能连接,输入ifconfig后如下图: 解决方法: 1.编辑网卡的配置文 ...
- CP-ABE ToolKit 安装笔记
博主论文狗,好久没有来贴博客,最近做实验需要用到属性加密,了解了下CP-ABE,前来记录一下: 网上相关的博文较多,博主看了大部分的,认为下面这两个看完了基本就可以成功安装. 可参见博文: http: ...
- Leecode刷题之旅-C语言/python-9.回文数
/* * @lc app=leetcode.cn id=9 lang=c * * [9] 回文数 * * https://leetcode-cn.com/problems/palindrome-num ...
- mtools使用-1
mtools是什么? mtools 是一组非常好用的 MongoDB 日志分析工具 ,由MongoDB Inc 官方工程师所写. 组成部分 mlogfilter :按时间切片日志文件,合并日志文件,过 ...
- Git更改远程仓库地址
最近在开发一个公司内部的公共组件库.老大整理了git仓库里的一些项目,其中就包括这个项目. 项目git地址变了,于是我本地的代码提交成功后push失败. 查看远程地址 git remote -v 更改 ...
- Git使用之一:创建仓储和提交文件
一.前期工作: 1.准备自己的文件夹用于同步文件 2.准备自己的Git账号,并设置好项目(推荐使用国产的码云) 3.安装Git软件 (下载地址: 32-bit Git for Window ...
- golang 小知识点记录
获取url中的参数及输出到页面的几种方式 func SayHello(w http.ResponseWriter, req *http.Request) { req.Method //获取url的方法 ...
- 为什么在默认情况下无法修改被block捕获的变量? __block都做了什么?
默认情况下,block里面的变量,拷贝进去的是变量的值,而不是指向变量的内存的指针.使用__block修饰后的变量,拷贝到block里面的就是指向变量的指针,所以我们就可以修改变量的值.
- java_hdfs之读写文件
package hdfsTest.answer.hdfs; import java.io.IOException; import java.net.URI; //import java.net.URL ...
- iOS笔记058 - IOS之多线程
IOS开发中多线程 主线程 一个iOS程序运行后,默认会开启1条线程,称为"主线程"或"UI线程" 作用 显示和刷新界面 处理UI事件(点击.滚动.拖拽等) 注 ...