| #include <iostream> |
| #include <vector> |
| #include <algorithm> |
| #include <random> |
| #include <chrono> |
|
|
| using namespace std; |
|
|
| |
| int n, m; |
| vector<int> a(10); |
| vector<vector<int>> adj; |
| vector<vector<int>> rev_adj; |
| vector<int> in_deg_static; |
| vector<int> out_deg_static; |
| vector<int> best_path; |
|
|
| |
| mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); |
|
|
| void solve() { |
| |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
|
|
| if (!(cin >> n >> m)) return; |
| for (int i = 0; i < 10; ++i) cin >> a[i]; |
|
|
| adj.assign(n + 1, vector<int>()); |
| rev_adj.assign(n + 1, vector<int>()); |
| in_deg_static.assign(n + 1, 0); |
| out_deg_static.assign(n + 1, 0); |
|
|
| for (int i = 0; i < m; ++i) { |
| int u, v; |
| cin >> u >> v; |
| adj[u].push_back(v); |
| rev_adj[v].push_back(u); |
| out_deg_static[u]++; |
| in_deg_static[v]++; |
| } |
|
|
| |
| vector<int> zero_in_nodes; |
| for (int i = 1; i <= n; ++i) { |
| if (in_deg_static[i] == 0) { |
| zero_in_nodes.push_back(i); |
| } |
| } |
|
|
| |
| vector<int> candidates; |
| if (zero_in_nodes.empty()) { |
| candidates.resize(n); |
| for(int i=0; i<n; ++i) candidates[i] = i + 1; |
| |
| shuffle(candidates.begin(), candidates.end(), rng); |
| |
| sort(candidates.begin(), candidates.end(), [&](int x, int y){ |
| return in_deg_static[x] < in_deg_static[y]; |
| }); |
| } |
|
|
| |
| vector<int> cur_out_deg(n + 1); |
| vector<char> visited(n + 1); |
| vector<int> path; |
| path.reserve(n); |
| vector<int> next_candidates; |
| next_candidates.reserve(100); |
|
|
| auto start_time = chrono::steady_clock::now(); |
| int cand_idx = 0; |
| int run_count = 0; |
|
|
| |
| while (true) { |
| run_count++; |
| |
| if ((run_count & 31) == 0) { |
| auto now = chrono::steady_clock::now(); |
| if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 3800) break; |
| } |
|
|
| |
| if ((int)best_path.size() == n) break; |
|
|
| |
| int start_node; |
| if (!zero_in_nodes.empty()) { |
| |
| |
| start_node = zero_in_nodes[0]; |
| } else { |
| |
| if (cand_idx < n) { |
| start_node = candidates[cand_idx]; |
| } else { |
| start_node = candidates[rng() % n]; |
| } |
| cand_idx++; |
| } |
|
|
| |
| for(int i=1; i<=n; ++i) { |
| cur_out_deg[i] = out_deg_static[i]; |
| visited[i] = 0; |
| } |
| path.clear(); |
|
|
| int curr = start_node; |
| visited[curr] = 1; |
| path.push_back(curr); |
|
|
| |
| for (int prev : rev_adj[curr]) { |
| if (!visited[prev]) cur_out_deg[prev]--; |
| } |
|
|
| |
| while (path.size() < n) { |
| int best_metric = 2e9; |
| next_candidates.clear(); |
|
|
| bool possible = false; |
| |
| for (int nxt : adj[curr]) { |
| if (!visited[nxt]) { |
| possible = true; |
| int d = cur_out_deg[nxt]; |
| |
| |
| int metric = (d == 0 ? 1000000 : d); |
| |
| if (metric < best_metric) { |
| best_metric = metric; |
| next_candidates.clear(); |
| next_candidates.push_back(nxt); |
| } else if (metric == best_metric) { |
| next_candidates.push_back(nxt); |
| } |
| } |
| } |
|
|
| if (!possible) break; |
|
|
| |
| int next_node; |
| if (next_candidates.size() == 1) { |
| next_node = next_candidates[0]; |
| } else { |
| |
| next_node = next_candidates[rng() % next_candidates.size()]; |
| } |
|
|
| curr = next_node; |
| visited[curr] = 1; |
| path.push_back(curr); |
| |
| |
| for (int prev : rev_adj[curr]) { |
| if (!visited[prev]) cur_out_deg[prev]--; |
| } |
| } |
|
|
| |
| if (path.size() > best_path.size()) { |
| best_path = path; |
| } |
| } |
|
|
| |
| cout << best_path.size() << "\n"; |
| for (int i = 0; i < (int)best_path.size(); ++i) { |
| cout << best_path[i] << (i == (int)best_path.size() - 1 ? "" : " "); |
| } |
| cout << "\n"; |
| } |
|
|
| int main() { |
| solve(); |
| return 0; |
| } |