Advertisement
erek1e

IOI '11 P1 - Tropical Garden (Standard I/O)

Jul 23rd, 2022
1,235
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.75 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <queue>
  5.  
  6. using namespace std;
  7.  
  8. const int INF = 1e9 + 10;
  9.  
  10. int main() {
  11.     int n, m, p;
  12.     cin >> n >> m >> p;
  13.     vector<vector<pair<int, int>>> g(n);
  14.     for (int i = 0; i < m; ++i) {
  15.         int u, v; cin >> u >> v;
  16.         g[u].emplace_back(i, v);
  17.         g[v].emplace_back(i, u);
  18.     }
  19.  
  20.     // split each node into two nodes:
  21.     //  - can exit through smallest edge
  22.     //  - cannot exit through smallest edge
  23.     vector<int> nxt(2*n);
  24.     for (int u = 0; u < n; ++u) {
  25.         sort(g[u].begin(), g[u].end());
  26.         nxt[2*u] = g[u][0].second; // will exit through smallest edge
  27.         nxt[2*u+1] = g[u][g[u].size() == 1 ? 0 : 1].second; // will exit through second smallest edge (if exists)
  28.     }
  29.     for (int u = 0; u < 2*n; ++u) {
  30.         nxt[u] <<= 1;
  31.         // entered nxt[u] through its smallest edge?
  32.         if (g[nxt[u]>>1][0].second == (u>>1)) ++nxt[u];
  33.     }
  34.  
  35.     // there are now two target nodes: 2*p and 2*p+1
  36.     int targetCycle[2]{INF, INF};
  37.     for (int target = 2*p; target <= 2*p+1; ++target) {
  38.         vector<bool> seen(2*n);
  39.         int cur = target, cycleSize = 0;
  40.         while (!seen[cur]) {
  41.             seen[cur] = true;
  42.             ++cycleSize;
  43.             cur = nxt[cur];
  44.         }
  45.         if (cur == target) targetCycle[target-2*p] = cycleSize;
  46.     }
  47.  
  48.     vector<vector<int>> prv(2*n);
  49.     for (int u = 0; u < 2*n; ++u) prv[nxt[u]].push_back(u);
  50.  
  51.     // reverse bfs from each target to find distances
  52.     vector<int> targetDistance[2];
  53.     for (int target = 2*p; target <= 2*p+1; ++target) {
  54.         int id = target-2*p;
  55.         targetDistance[id] = vector<int>(2*n, INF);
  56.         queue<int> q;
  57.         q.push(target);
  58.         targetDistance[id][target] = 0;
  59.         while (!q.empty()) {
  60.             int v = q.front();
  61.             q.pop();
  62.             for (int u : prv[v]) {
  63.                 if (targetDistance[id][u] == INF) {
  64.                     targetDistance[id][u] = targetDistance[id][v] + 1;
  65.                     q.push(u);
  66.                 }
  67.             }
  68.         }
  69.     }
  70.  
  71.     int q; cin >> q;
  72.     while (q--) {
  73.         int k, ans = 0; cin >> k;
  74.         for (int i = 0; i < n; ++i) {
  75.             int u = 2*i; // must start in node that can exit through smallest
  76.             bool can = false;
  77.             // check to see if it can reach either target node in k moves
  78.             for (int target = 2*p; target <= 2*p+1 && !can; ++target) {
  79.                 int id = target-2*p;
  80.                 if (targetDistance[id][u] > k) continue;
  81.                 can = (k - targetDistance[id][u]) % targetCycle[id] == 0;
  82.             }
  83.             ans += can;
  84.         }
  85.         cout << ans << ' ';
  86.     }
  87.     cout << endl;
  88.     return 0;
  89. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement