zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    在Unix上使用管道压缩exp导出文件
    自制CPU的黑暗历程一
    Error C1189: #error: Please use the /MD switch for _AFXDLL builds
    Redis乐观锁解决高并发抢红包的问题
    PHP分页类
    汇编基础——使用nasm和bochs学习汇编
    数据同步工具DBsync
    完成端口的一些教程
    sdf
    (转)C#(WIN FORM)两个窗体间LISTVIEW值的修改
  • 原文地址:https://www.cnblogs.com/Saurus/p/5967279.html
Copyright © 2011-2022 走看看