| #include <iostream> |
| #include <vector> |
| #include <algorithm> |
| #include <stack> |
| #include <random> |
| #include <chrono> |
| #include <queue> |
|
|
| using namespace std; |
|
|
| const int MAXN = 500005; |
| const int INF = 1e9; |
|
|
| vector<int> adj[MAXN]; |
| vector<int> rev_adj[MAXN]; |
| int n, m; |
| int a_scores[10]; |
|
|
| |
| int dfn[MAXN], low[MAXN], timer; |
| int scc[MAXN], scc_cnt; |
| bool in_stack[MAXN]; |
| stack<int> st; |
| int scc_size[MAXN]; |
|
|
| |
| int scc_rank[MAXN]; |
|
|
| |
| bool visited[MAXN]; |
| vector<int> path; |
| vector<int> best_path; |
| int cnt_visited_in_scc[MAXN]; |
|
|
| |
| bool is_exit[MAXN]; |
| int dist_to_exit[MAXN]; |
|
|
| |
| mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); |
|
|
| void tarjan(int u) { |
| dfn[u] = low[u] = ++timer; |
| st.push(u); |
| in_stack[u] = true; |
| |
| for (int v : adj[u]) { |
| if (!dfn[v]) { |
| tarjan(v); |
| low[u] = min(low[u], low[v]); |
| } else if (in_stack[v]) { |
| low[u] = min(low[u], dfn[v]); |
| } |
| } |
| |
| if (low[u] == dfn[u]) { |
| scc_cnt++; |
| while (true) { |
| int v = st.top(); |
| st.pop(); |
| in_stack[v] = false; |
| scc[v] = scc_cnt; |
| scc_size[scc_cnt]++; |
| if (u == v) break; |
| } |
| } |
| } |
|
|
| auto start_time = chrono::steady_clock::now(); |
| bool time_limit_exceeded() { |
| auto curr = chrono::steady_clock::now(); |
| return chrono::duration_cast<chrono::milliseconds>(curr - start_time).count() > 3800; |
| } |
|
|
| bool solve_dfs(int u) { |
| if (time_limit_exceeded()) return false; |
| |
| visited[u] = true; |
| path.push_back(u); |
| int u_scc = scc[u]; |
| cnt_visited_in_scc[u_scc]++; |
| |
| if (path.size() > best_path.size()) { |
| best_path = path; |
| } |
| |
| if (best_path.size() == n) return true; |
| |
| int u_rank = scc_rank[u_scc]; |
| |
| for (int v : adj[u]) { |
| if (visited[v]) continue; |
| |
| int v_scc = scc[v]; |
| int v_rank = scc_rank[v_scc]; |
| |
| if (v_rank == u_rank) { |
| if (solve_dfs(v)) return true; |
| } else if (v_rank == u_rank + 1) { |
| if (cnt_visited_in_scc[u_scc] == scc_size[u_scc]) { |
| if (solve_dfs(v)) return true; |
| } |
| } |
| |
| if (time_limit_exceeded()) break; |
| } |
| |
| visited[u] = false; |
| path.pop_back(); |
| cnt_visited_in_scc[u_scc]--; |
| return false; |
| } |
|
|
| int main() { |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
| |
| if (!(cin >> n >> m)) return 0; |
| |
| for (int i = 0; i < 10; ++i) cin >> a_scores[i]; |
| |
| for (int i = 0; i < m; ++i) { |
| int u, v; |
| cin >> u >> v; |
| adj[u].push_back(v); |
| rev_adj[v].push_back(u); |
| } |
| |
| for (int i = 1; i <= n; ++i) { |
| if (!dfn[i]) tarjan(i); |
| } |
| |
| for (int i = 1; i <= scc_cnt; ++i) { |
| scc_rank[i] = scc_cnt - i; |
| } |
| |
| |
| for (int u = 1; u <= n; ++u) { |
| dist_to_exit[u] = INF; |
| int r = scc_rank[scc[u]]; |
| for (int v : adj[u]) { |
| if (scc_rank[scc[v]] == r + 1) { |
| is_exit[u] = true; |
| break; |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| queue<int> q; |
| for (int u = 1; u <= n; ++u) { |
| if (is_exit[u]) { |
| dist_to_exit[u] = 0; |
| q.push(u); |
| } |
| } |
| |
| while (!q.empty()) { |
| int u = q.front(); |
| q.pop(); |
| |
| int u_scc = scc[u]; |
| for (int v : rev_adj[u]) { |
| if (scc[v] == u_scc) { |
| if (dist_to_exit[v] == INF) { |
| dist_to_exit[v] = dist_to_exit[u] + 1; |
| q.push(v); |
| } |
| } |
| } |
| } |
| |
| |
| for (int i = 1; i <= n; ++i) { |
| shuffle(adj[i].begin(), adj[i].end(), rng); |
| |
| sort(adj[i].begin(), adj[i].end(), [&](int a, int b) { |
| int r_a = scc_rank[scc[a]]; |
| int r_b = scc_rank[scc[b]]; |
| int r_u = scc_rank[scc[i]]; |
| |
| |
| bool same_rank_a = (r_a == r_u); |
| bool same_rank_b = (r_b == r_u); |
| |
| if (same_rank_a != same_rank_b) { |
| return same_rank_a; |
| } |
| |
| if (same_rank_a) { |
| |
| |
| |
| |
| return dist_to_exit[a] > dist_to_exit[b]; |
| } else { |
| |
| |
| return dist_to_exit[a] > dist_to_exit[b]; |
| } |
| }); |
| } |
| |
| |
| int first_scc_id = scc_cnt; |
| vector<int> starts; |
| for (int i = 1; i <= n; ++i) { |
| if (scc[i] == first_scc_id) { |
| starts.push_back(i); |
| } |
| } |
| |
| |
| sort(starts.begin(), starts.end(), [&](int a, int b) { |
| return dist_to_exit[a] > dist_to_exit[b]; |
| }); |
| |
| |
| for (int start_node : starts) { |
| if (solve_dfs(start_node)) break; |
| if (time_limit_exceeded()) break; |
| } |
| |
| cout << best_path.size() << "\n"; |
| for (size_t i = 0; i < best_path.size(); ++i) { |
| cout << best_path[i] << (i == best_path.size() - 1 ? "" : " "); |
| } |
| cout << "\n"; |
| |
| return 0; |
| } |