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 ...
随机推荐
- php-5.6.26源代码 - include_once、require_once、include、require、eval 的opcode处理器
# ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER 实现在文件 php-\Zend\zend_vm_execute.h static int ZEND_FASTCALL ...
- 一次 group by + order by 性能优化分析
一次 group by + order by 性能优化分析 最近通过一个日志表做排行的时候发现特别卡,最后问题得到了解决,梳理一些索引和MySQL执行过程的经验,但是最后还是有5个谜题没解开,希望大家 ...
- Windows 10 登录界面的背景图片地址
C:\Users\******\appdata\Local\Packages\Microsoft.Windows.ContentDeliveryManager_********\LocalState\ ...
- PublicCMS 网站漏洞 任意文件写入并可提权服务器权限
PublicCMS是目前网站系统中第一个采用JAVA架构 TOMCAT+Apcche+Mysql数据库架构的CMS网站,开源,数据承载量大,可以承载到上千万的数据量,以及用户的网站并发可达到上千万的P ...
- 洛谷P4016 负载平衡问题
题目描述 G 公司有 n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入输出格式 输入格式: ...
- Java——equals方法---18.10.18
一.equals方法定义 public boolean equals(Object obj)方法 //提供对象是否“相等”的逻辑 二.”equals“和“==”的区别 1.“==”比较的是两个变量本身 ...
- 总结Verilog中always语句的使用
always语句包括的所有行为语句构成了一个always语句块.该always语句块从仿真0时刻开始执行其中的行为语句:最后一条执行完成后,再开始执行其中的第一条语句,如此往复循环,直到整个仿真结束. ...
- 如何打war包
1. 利用jdk里的工具 例如我们要打包的文件在D:\myHome\dist: 运行 cmd: cd D:\myHome\dist 进入D:\myHome\dist 然后输入 D:\myHome\di ...
- Flexbox布局模式的理解
个人博客地址: 雨中的鱼-前端知识分享 http://www.showhtml5.cc 分享干货,有兴趣的人可以一起来分享前端知识 加Q群:440279380 Flexbox,一种C ...
- github简单使用教程(转)
github是一个基于git的代码托管平台,付费用户可以建私人仓库,我们一般的免费用户只能使用公共仓库,也就是代码要公开.对于一般人来说公共仓库就已经足够了,而且我们也没多少代码来管理,O(∩_∩)O ...