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 ...
随机推荐
- Keepalived搭建主从架构、主主架构实例
实例拓扑图: DR1和DR2部署Keepalived和lvs作主从架构或主主架构,RS1和RS2部署nginx搭建web站点. 注意:各节点的时间需要同步(ntpdate ntp1.aliyun.co ...
- linux总结及常用命令
一.操作系统的作用: 1.是现代计算机系统中最基本和最重要的系统软件 2.承上启下的作用 3.向下对硬件操作进行封装 4.向上对用户和应用程序提供方便访问硬件的接口 二.不同领域的操作系统: 1 ...
- linux文件IO操作篇 (一) 非缓冲文件
文件IO操作分为 2 种 非缓冲文件IO 和 缓冲文件IO 它们的接口区别是 非缓冲 open() close() read() write() 缓冲 fopen() fclose() fread() ...
- java web项目使用ant编译将不同的功能代码打包成jar,进而分局点将项目打包成不同的tar.gz包进而部署
使用ant可以轻松的将一个项目分离代码,直接打包成不同需求的tar.gz包使用 1.build.properties (属性) version.num=1.0 #版本信息 2.build.xml (a ...
- stm32--USB(作为U盘)+FatFs的实现
一.USB功能的添加(作为U盘) 添加文件 将官方库中的Library文件夹中的所有有效文件添加到工程中,分为4个文件夹: usb class为硬件相关(Library\Class): usb dri ...
- Java Algorithm Problems
Java Algorithm Problems 程序员的一天 从开始这个Github已经有将近两年时间, 很高兴这个repo可以帮到有需要的人. 我一直认为, 知识本身是无价的, 因此每逢闲暇, 我就 ...
- c++ list_iterator demo
#include <iostream> #include <list> using namespace std; typedef list<int> Integer ...
- Scala学习笔记(三):基础知识
有了可运行的环境,就需要写一些简单的语句来认识一下Scala,本文没有写那么详细,只是为了方便查看.唤起回忆 (1)变量的定义方法 Scala有两种变量 var val 注意:在解释器中,可以用一个之 ...
- Wireshark lua dissector 对TCP消息包合并分析
应用程序发送的数据报都是流式的,IP不保证同一个一个应用数据包会被抓包后在同一个IP数据包中,因此对于使用自制dissector的时候需要考虑这种情况. Lua Dissector相关资料可以见:ht ...
- Eclipse+APKTool动态调试APK
1. 所需工具 Eclipse. Apktool v2.0.6. 安卓SDK工具. 2. 重编译APK apktool d -d -o test test.apk 此时当前test目录下就是apkto ...