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 ...
随机推荐
- Linux环境下tomcat如何热部署
1.修改tomcat配置文件 1.1第一步修改tomcat-users.xml <role rolename="manager-gui" /> <role rol ...
- python实现归并排序,归并排序的详细分析
python实现归并排序,归并排序的详细分析. 学习归并排序的过程是十分痛苦的.它并不常用,看起来时间复杂度好像是几种排序中最低的,比快排的时间复杂度还要低,但是它的执行速度不是最快的.很多朋友不 ...
- java递归 斐波那契数列递归与非递归实现
递归简单来说就是自己调用自己, 递归构造包括两个部分: 1.定义递归头:什么时候需要调用自身方法,如果没有头,将陷入死循环 2.递归体:调用自身方法干什么 递归是自己调用自己的方法,用条件来判断调用什 ...
- js中的逻辑与和逻辑或随笔
逻辑与:&&,都真才真 逻辑或:||,一真都真 逻辑运算两侧不都是布尔值时,会隐式转换为布尔值转换规则:转换为true:非0数字(包含infinity).非空字符串转换为false:0 ...
- 一、Linux知识体系结构图
参考: https://blog.csdn.net/Swing_Liu/article/details/79202479
- linux c fprintf()
#include<stdio.h> #include<unistd.h> #include<time.h> int main(int argc,char *argv ...
- WebService第一天——概述与入门操作
一.概述 1.是什么 Web service是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述.发布.发现.协调和配置这些 ...
- ionic 入口禁止加载其他页面
.state('memberOrders', { prefetchTemplate: false, url: '/memberOrders', templateUrl: '/MemberOrders' ...
- PHP管理供下载的APK文件
当我们开发的APP多的时候,把所有的APK文件统一放到一个目录中管理,是一个不错的选择: 管理的方法有很多,这里说一种: 1..创建目录结构,先创建根目录download,在根目录中创建项目目录,在项 ...
- jmeter之HTTP请求
1.添加一个线程组:Test plan_添加_Threads(users)_线程组(右键操作),如下图: 2.添加一个HTTP请求:线程组_添加_sample_HTTP请求(右键操作),如下图: 3. ...