| #include <iostream> |
| #include <vector> |
| #include <algorithm> |
| #include <stack> |
| #include <random> |
| #include <chrono> |
|
|
| using namespace std; |
|
|
| const int MAXN = 500005; |
|
|
| int n, m; |
| int a[10]; |
| vector<int> adj[MAXN]; |
|
|
| |
| int dfn[MAXN], low[MAXN], timer; |
| int stk[MAXN], top; |
| bool in_stk[MAXN]; |
| int scc[MAXN], scc_cnt; |
| int scc_size[MAXN]; |
|
|
| void tarjan(int u) { |
| dfn[u] = low[u] = ++timer; |
| stk[++top] = u; |
| in_stk[u] = true; |
| for (int v : adj[u]) { |
| if (!dfn[v]) { |
| tarjan(v); |
| low[u] = min(low[u], low[v]); |
| } else if (in_stk[v]) { |
| low[u] = min(low[u], dfn[v]); |
| } |
| } |
| if (low[u] == dfn[u]) { |
| scc_cnt++; |
| int v; |
| do { |
| v = stk[top--]; |
| in_stk[v] = false; |
| scc[v] = scc_cnt; |
| scc_size[scc_cnt]++; |
| } while (u != v); |
| } |
| } |
|
|
| |
| vector<int> scc_adj[MAXN]; |
| int in_degree[MAXN]; |
| int scc_rank[MAXN]; |
| int scc_sz_by_rank[MAXN]; |
| vector<int> nodes_in_scc[MAXN]; |
|
|
| |
| bool visited[MAXN]; |
| int current_scc_visited[MAXN]; |
| vector<int> adj_sorted[MAXN]; |
| int out_deg_same[MAXN]; |
|
|
| |
| mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); |
|
|
| |
| long long operations = 0; |
| const long long MAX_OPS = 90000000; |
| bool found = false; |
|
|
| struct State { |
| int u; |
| int idx; |
| }; |
|
|
| vector<int> best_path; |
|
|
| void solve() { |
| |
| for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i); |
| |
| |
| for (int u = 1; u <= n; u++) { |
| for (int v : adj[u]) { |
| if (scc[u] != scc[v]) { |
| scc_adj[scc[u]].push_back(scc[v]); |
| in_degree[scc[v]]++; |
| } |
| } |
| } |
| |
| |
| vector<int> q; |
| for (int i = 1; i <= scc_cnt; i++) { |
| sort(scc_adj[i].begin(), scc_adj[i].end()); |
| scc_adj[i].erase(unique(scc_adj[i].begin(), scc_adj[i].end()), scc_adj[i].end()); |
| if (in_degree[i] == 0) q.push_back(i); |
| } |
| |
| vector<int> topo_order; |
| int head = 0; |
| while(head < q.size()){ |
| int u = q[head++]; |
| topo_order.push_back(u); |
| for(int v : scc_adj[u]){ |
| in_degree[v]--; |
| if(in_degree[v] == 0) q.push_back(v); |
| } |
| } |
| |
| |
| |
| |
| for(int i=0; i<topo_order.size(); ++i){ |
| scc_rank[topo_order[i]] = i; |
| scc_sz_by_rank[i] = scc_size[topo_order[i]]; |
| nodes_in_scc[i].reserve(scc_size[topo_order[i]]); |
| } |
| |
| for(int i=1; i<=n; ++i){ |
| nodes_in_scc[scc_rank[scc[i]]].push_back(i); |
| } |
|
|
| |
| for(int u=1; u<=n; ++u){ |
| int r_u = scc_rank[scc[u]]; |
| for(int v : adj[u]){ |
| if(scc_rank[scc[v]] == r_u) { |
| out_deg_same[u]++; |
| } |
| } |
| } |
|
|
| |
| |
| for(int u=1; u<=n; ++u){ |
| int r_u = scc_rank[scc[u]]; |
| vector<pair<int, int>> neighbors; |
| for(int v : adj[u]){ |
| int r_v = scc_rank[scc[v]]; |
| if(r_v == r_u) { |
| neighbors.push_back({0, v}); |
| } else if (r_v == r_u + 1) { |
| neighbors.push_back({1, v}); |
| } |
| |
| |
| } |
| |
| sort(neighbors.begin(), neighbors.end(), [&](const pair<int,int>& a, const pair<int,int>& b){ |
| if(a.first != b.first) return a.first < b.first; |
| if(a.first == 0) { |
| |
| return out_deg_same[a.second] < out_deg_same[b.second]; |
| } |
| return false; |
| }); |
| |
| for(auto &p : neighbors) adj_sorted[u].push_back(p.second); |
| } |
|
|
| |
| vector<int>& start_nodes = nodes_in_scc[0]; |
| vector<State> dfs_stack; |
| dfs_stack.reserve(n); |
| |
| while(operations < MAX_OPS && !found) { |
| |
| for(int i=1; i<=n; ++i) visited[i] = false; |
| for(int i=0; i<scc_cnt; ++i) current_scc_visited[i] = 0; |
| dfs_stack.clear(); |
| |
| if(start_nodes.empty()) break; |
| int start_node = start_nodes[rng() % start_nodes.size()]; |
| |
| visited[start_node] = true; |
| current_scc_visited[scc_rank[scc[start_node]]]++; |
| dfs_stack.push_back({start_node, 0}); |
| |
| |
| if(dfs_stack.size() > best_path.size()){ |
| best_path.clear(); |
| for(auto &st : dfs_stack) best_path.push_back(st.u); |
| } |
|
|
| while(!dfs_stack.empty()){ |
| operations++; |
| if(operations > MAX_OPS) break; |
| |
| State &top_state = dfs_stack.back(); |
| int u = top_state.u; |
| |
| if(dfs_stack.size() == n) { |
| found = true; |
| break; |
| } |
| |
| int next_v = -1; |
| int r_u = scc_rank[scc[u]]; |
| |
| |
| while(top_state.idx < adj_sorted[u].size()){ |
| int v = adj_sorted[u][top_state.idx]; |
| top_state.idx++; |
| |
| if(!visited[v]){ |
| int r_v = scc_rank[scc[v]]; |
| bool can_go = false; |
| if(r_v == r_u) { |
| can_go = true; |
| } else if (r_v == r_u + 1) { |
| |
| if(current_scc_visited[r_u] == scc_sz_by_rank[r_u]){ |
| can_go = true; |
| } |
| } |
| |
| if(can_go){ |
| next_v = v; |
| break; |
| } |
| } |
| } |
| |
| if(next_v != -1) { |
| visited[next_v] = true; |
| current_scc_visited[scc_rank[scc[next_v]]]++; |
| dfs_stack.push_back({next_v, 0}); |
| |
| |
| if(dfs_stack.size() > best_path.size()){ |
| best_path.clear(); |
| for(auto &st : dfs_stack) best_path.push_back(st.u); |
| } |
| } else { |
| |
| visited[u] = false; |
| current_scc_visited[scc_rank[scc[u]]]--; |
| dfs_stack.pop_back(); |
| } |
| } |
| |
| if(found) { |
| best_path.clear(); |
| for(auto &st : dfs_stack) best_path.push_back(st.u); |
| break; |
| } |
| } |
| } |
|
|
| 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[i]; |
| for(int i=0; i<m; ++i){ |
| int u, v; |
| cin >> u >> v; |
| adj[u].push_back(v); |
| } |
| |
| solve(); |
| |
| cout << best_path.size() << "\n"; |
| for(int i=0; i<best_path.size(); ++i){ |
| cout << best_path[i] << (i == best_path.size()-1 ? "" : " "); |
| } |
| cout << "\n"; |
| |
| return 0; |
| } |