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 迭代

  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 }

 

posted @ 2016-10-16 18:02  Saurus  阅读(321)  评论(0编辑  收藏  举报