#include <iostream>
#include <iterator>
#include <memory>
#include <vector>
#include <deque>
#include <set>
#include <unordered_map>
#include <algorithm>
#include <functional>
using namespace std;
void answer(int X);
struct pair_hash {
size_t operator()(const pair<int, int>& p) const {
return hash<int>()(p.first) ^ (hash<int>()(p.second) << 1);
}
};
void count_routes(int N, int M, int P, int R[][2], int Q, int G[]) {
vector<vector<int>> node_edges(N + 1);
for (int idx = 0; idx < M; ++idx) {
int i = R[idx][0];
int j = R[idx][1];
if (node_edges[i].size() < 2) {
node_edges[i].push_back(j);
}
if (node_edges[j].size() < 2) {
node_edges[j].push_back(i);
}
}
auto do_walk = [&](int walk, int prev_walk) {
if (node_edges[walk].empty()) {
return walk;
}
int next_walk = node_edges[walk][0];
if (node_edges[walk].size() == 2 && next_walk == prev_walk) {
next_walk = node_edges[walk][1];
}
return next_walk;
};
unordered_map<pair<int,int>, int, pair_hash> state_to_cycle_start_pos;
unordered_map<pair<int,int>, int, pair_hash> state_to_path_pos;
unordered_map<pair<int,int>, shared_ptr<deque<pair<int,int>>>, pair_hash> state_to_path_with_cycle;
auto can_from_node = [&](int node, int g) {
auto path = make_shared<deque<pair<int,int>>>();
set<pair<int,int>> visited;
int prev_walk = node;
int walk = do_walk(prev_walk, -1);
int next_walk = do_walk(walk, prev_walk);
while (g > 0) {
--g;
pair<int,int> state = {walk, next_walk};
// Cache hit: fast-forward through cycle
if (state_to_path_pos.count(state)) {
int path_pos = state_to_path_pos[state];
int cycle_start = state_to_cycle_start_pos[state];
auto cyc_path = state_to_path_with_cycle[state];
int cycle_size = int(cyc_path->size()) - cycle_start;
int g_rem;
if (path_pos >= cycle_start) {
g_rem = g + (path_pos - cycle_start);
} else if (path_pos + g >= cycle_start) {
g_rem = g - (cycle_start - path_pos);
} else {
return (*cyc_path)[path_pos + g].first == P;
}
int idx = cycle_start + (g_rem % cycle_size);
return (*cyc_path)[idx].first == P;
}
// First time in this state
if (visited.insert(state).second) {
path->push_back(state);
int prev = walk;
walk = do_walk(walk, prev_walk);
if (prev == walk) {
return walk == P;
}
prev_walk = prev;
next_walk = do_walk(walk, prev_walk);
}
// Found a cycle
else {
auto it = find(path->begin(), path->end(), state);
int cycle_start = int(distance(path->begin(), it));
for (int i = 0; i < (int)path->size(); ++i) {
auto s = (*path)[i];
state_to_path_pos[s] = i;
state_to_cycle_start_pos[s] = cycle_start;
state_to_path_with_cycle[s] = path;
}
int cycle_len = int(path->size()) - cycle_start;
return (*path)[cycle_start + (g % cycle_len)].first == P;
}
}
return path->back().first == P;
};
for (int i = 0; i < Q; ++i) {
int cnt = 0;
for (int node = 0; node < N; ++node) {
if (can_from_node(node, G[i])) {
++cnt;
}
}
answer(cnt);
}
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |