#include #include #include #include #include #include using namespace std; const int MAXN = 500005; int n, m; int a[10]; vector adj[MAXN]; // Tarjan's Algorithm for SCC 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); } } // Logic variables vector scc_adj[MAXN]; int in_degree[MAXN]; int scc_rank[MAXN]; // Topological order rank int scc_sz_by_rank[MAXN]; vector nodes_in_scc[MAXN]; // DFS Solver state bool visited[MAXN]; int current_scc_visited[MAXN]; // Count of visited nodes in each scc rank vector adj_sorted[MAXN]; int out_deg_same[MAXN]; // Helper for Warnsdorff's heuristic // Random number generator mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); // Backtracking control long long operations = 0; const long long MAX_OPS = 90000000; // Heuristic operation limit bool found = false; struct State { int u; int idx; // current index in adj_sorted[u] }; vector best_path; void solve() { // 1. Find SCCs for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i); // 2. Build Condensation Graph 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]]++; } } } // 3. Topological Sort of SCCs vector 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 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); } } // 4. Assign ranks based on topological order // Since a Hamiltonian Path exists, the condensation graph must allow a linear traversal. // The topological sort index effectively gives the order of SCCs in that path. for(int i=0; i> neighbors; // {priority, v} 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}); } // Edges skipping SCCs (u -> u+k where k>1) or going back are ignored // because they violate the Hamiltonian Path structure (must visit all nodes). } sort(neighbors.begin(), neighbors.end(), [&](const pair& a, const pair& b){ if(a.first != b.first) return a.first < b.first; if(a.first == 0) { // For same SCC, use Warnsdorff's rule: pick neighbor with fewer available moves. return out_deg_same[a.second] < out_deg_same[b.second]; } return false; }); for(auto &p : neighbors) adj_sorted[u].push_back(p.second); } // 7. Randomized DFS with Backtracking/Restarts vector& start_nodes = nodes_in_scc[0]; vector dfs_stack; dfs_stack.reserve(n); while(operations < MAX_OPS && !found) { // Reset state for new attempt for(int i=1; i<=n; ++i) visited[i] = false; for(int i=0; i 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]]; // Try to find a valid next neighbor 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) { // Can only move to next SCC if we visited all nodes in current SCC 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}); // Update best path if this path is longer if(dfs_stack.size() > best_path.size()){ best_path.clear(); for(auto &st : dfs_stack) best_path.push_back(st.u); } } else { // Backtrack 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> u >> v; adj[u].push_back(v); } solve(); cout << best_path.size() << "\n"; for(int i=0; i