NOIP 2017 逛公園 - 動態規劃 - 最短路

題目傳送門ios

  傳送門spa

題目大意code

  給定一個$n$個點$m$條邊的帶權有向圖,問從$1$到$n$的距離不超過最短路長度$K$的路徑數。blog

  跑一遍最短路。排序

  一個點拆$K + 1$個點,變成一個DAG上路徑計數問題。直接拓撲排序加動態規劃,若是有一個$n$號點的剩餘度數非0,就一個合法的路徑上存在零環(這樣能夠無線走了)。ci

  因而成功T掉了。get

  把拓撲排序變成不建圖,從$n$開始記憶化搜索,而後就過了。it

  我竟然把模數P打錯成M調了一個上午,果真我菜啊。。。io

Code

  1 /**
  2  * Uoj
  3  * Problem#331
  4  * Accepted
  5  * Time: 2392ms
  6  * Memory: 28196k
  7  */
  8 #include <iostream>
  9 #include <cassert>
 10 #include <cstdlib>
 11 #include <cstdio>
 12 #include <vector>
 13 #include <queue>
 14 using namespace std;
 15 typedef bool boolean;
 16 
 17 typedef pair<int, int> pii;
 18 
 19 const int N = 1e5 + 5, M = 2e5 + 5, Kmx = 52;
 20 
 21 const signed int inf = (signed) (~0u >> 1);
 22 
 23 template <typename T>
 24 void pfill(T* pst, const T* ped, T val) {
 25     for ( ; pst != ped; *(pst++) = val);
 26 }
 27 
 28 typedef class Edge {
 29     public:
 30         int ed, nx, w;
 31 
 32         Edge(int ed = 0, int nx = 0, int w = 0):ed(ed), nx(nx), w(w) {    }
 33 }Edge;
 34 
 35 typedef class MapManager {
 36     public:
 37         int *h;
 38         vector<Edge> es;
 39 
 40         MapManager(int n) {
 41             h = new int[(n + 1)];
 42         }
 43 
 44         void init(int n) {
 45             pfill(h + 1, h + n + 1, -1);
 46             es.clear();
 47         }    
 48 
 49         void addEdge(int u, int v, int w) {
 50             es.push_back(Edge(v, h[u], w));
 51             h[u] = (signed) es.size() - 1;        
 52         }
 53 
 54         Edge& operator [] (int p) {
 55             return es[p];
 56         }
 57 }MapManager;
 58 
 59 typedef class Node {
 60     public:
 61         int p, dis;
 62 
 63         Node(int p = 0, int dis = 0):p(p), dis(dis) {    }
 64 
 65         boolean operator < (Node b) const {
 66             return dis > b.dis;
 67         }
 68 }Node;
 69 
 70 int n, m, K, P;
 71 MapManager g(N), _g(N);
 72 
 73 int add(int a, int b) {
 74     return ((a += b) >= P) ? (a - P) : (a);
 75 }
 76 
 77 inline void init() {
 78     scanf("%d%d%d%d", &n, &m, &K, &P);
 79     g.init(n + 1), _g.init(n + 1);
 80     for (int i = 1, u, v, w; i <= m; i++) {
 81         scanf("%d%d%d", &u, &v, &w);
 82         g.addEdge(u, v, w);
 83         _g.addEdge(v, u, w);
 84     }
 85 }
 86 
 87 int f[N];
 88 priority_queue<Node> que;
 89 
 90 int& operator * (Node p) {
 91     return f[p.p];
 92 }
 93 
 94 void dijstra() {
 95     pfill(f + 1, f + n + 1, inf);
 96     que.push(Node(1, f[1] = 0));
 97     while (!que.empty()) {
 98         Node e = que.top();
 99         que.pop();
100         if (*e != e.dis)
101             continue;
102         for (int i = g.h[e.p]; ~i; i = g[i].nx)
103             if (*e + g[i].w < f[g[i].ed])
104                 que.push(Node(g[i].ed, f[g[i].ed] = *e + g[i].w));
105     }
106 }
107 
108 int h[N][Kmx];
109 unsigned char vis[N][Kmx];
110 boolean cir = false;
111 int dp(int p, int dif) {
112     if (dif > K)
113         return 0;
114     if (dif < 0)
115         return 0;
116     assert(dif >= 0);
117     if (vis[p][dif] & 2)
118         return cir = true;
119     if (vis[p][dif] & 1)
120         return h[p][dif];
121     vis[p][dif] |= 3, h[p][dif] = (p == 1 && dif == 0);
122     for (int i = _g.h[p], e, nd; ~i; i = _g[i].nx) {
123         e = _g[i].ed;
124         if (f[e] == inf)
125             continue;
126         nd = f[p] + dif - _g[i].w - f[e];
127         h[p][dif] = add(h[p][dif], dp(e, nd));
128         if (cir)
129             return 0;
130     }
131     vis[p][dif] ^= 2;
132     return h[p][dif];
133 }
134 
135 inline void solve() {
136     dijstra();
137     if (f[n] == inf) {
138         puts("0");
139         return;
140     }
141     cir = false;
142     pfill(vis[1], vis[n + 1], (unsigned char)0);
143     int rt = dp(n, 0);
144     for (int i = 1; i <= K && !cir; i++)
145         rt = add(rt, dp(n, i));
146     printf("%d\n", (cir) ? (-1) : (rt));
147 }
148 
149 int T;
150 int main() {
151     scanf("%d", &T);
152     while (T--) {
153         init();
154         solve();
155     }
156     return 0;
157 }
相關文章
相關標籤/搜索