题意
在一个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 迭代
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <stack> 6 #include <queue> 7 #include <map> 8 using namespace std; 9 const int Maxn = 5050; 10 int n, m, T; 11 struct Edge 12 { 13 int front, to, t; 14 }; 15 vector <Edge> edges; 16 vector <short int> G[Maxn]; 17 short int R[Maxn]; 18 bool flag[Maxn]; 19 queue<short int> Tp; 20 void AddEdge(int u, int v, int tt) 21 { 22 edges.push_back((Edge){u, v, tt}); 23 R[v]++; 24 G[u].push_back(edges.size()-1); 25 } 26 27 struct dp 28 { 29 int N_T[Maxn], D; 30 vector<int> Q; 31 map<short int, short int> f, N_N; 32 dp() 33 { 34 f.clear(); N_N.clear(); Q.clear(); 35 } 36 void update(dp B, int t) 37 { 38 for(int i = 0; i < B.Q.size(); i++) 39 { 40 int k = B.Q[i]; 41 if(f[k+1]) 42 { 43 if(N_T[k+1] > B.N_T[k] + t) 44 { 45 N_T[k+1] = B.N_T[k] + t; 46 N_N[k+1] = B.D; 47 } 48 }else 49 { 50 if(B.N_T[k] + t > T) continue; 51 N_T[k+1] = B.N_T[k] + t; 52 N_N[k+1] = B.D; 53 f[k+1] = true; 54 Q.push_back(k+1); 55 } 56 } 57 } 58 void clear() 59 { 60 Q.clear(); f.clear(); 61 } 62 }Dp[Maxn]; 63 int main() 64 { 65 //freopen("a.txt", "r", stdin); 66 memset(flag, 0, sizeof(flag)); 67 memset(R, 0, sizeof(R)); 68 int u, v, t; 69 cin>>n>>m>>T; 70 71 for(int i = 0; i < n; i++) G[i].clear(); edges.clear(); 72 73 for(int i = 1; i <= m; i++) 74 { 75 cin>>u>>v>>t; 76 AddEdge(u, v, t); 77 } 78 for(int k = 1; k <= n; k++) 79 { 80 for(int i = 1; i <= n; i++) 81 { 82 if(flag[i]) continue; 83 if(R[i] == 0) 84 { 85 for(int x = 0; x < G[i].size(); x++) 86 R[edges[G[i][x]].to]--; 87 Tp.push(i); flag[i] = true; 88 break; 89 } 90 } 91 } 92 93 Dp[1].N_T[1] = 0; Dp[1].Q.push_back(1); 94 for(int i = 1; i <= n; i++) Dp[i].D = i; 95 96 while(!Tp.empty()) 97 { 98 int x = Tp.front(); Tp.pop(); 99 for(int u = 0; u < G[x].size(); u++) 100 { 101 Edge &e = edges[G[x][u]]; 102 Dp[e.to].update(Dp[x], e.t); 103 } 104 if(x != n) Dp[x].clear(); 105 } 106 107 int Max = 0, x = n; 108 for(int i = 0; i < Dp[n].Q.size(); i++) Max = ((Max < Dp[n].Q[i]) ? Dp[n].Q[i] : Max); 109 cout<<Max<<endl; 110 stack<short int> S; 111 while(x != 1) 112 { 113 S.push(x); 114 x = Dp[x].N_N[Max]; 115 Max--; 116 } 117 printf("1 "); 118 while(!S.empty()) 119 { 120 printf("%d ", S.top()); 121 S.pop(); 122 } 123 }