| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| int main() { |
| ios::sync_with_stdio(false); |
| cin.tie(nullptr); |
| |
| int n, m; |
| if (!(cin >> n >> m)) return 0; |
| int a_dummy; |
| for (int i = 0; i < 10; ++i) cin >> a_dummy; |
| |
| vector<vector<int>> out(n + 1), in(n + 1); |
| out.reserve(n + 1); |
| in.reserve(n + 1); |
| for (int i = 0; i < m; ++i) { |
| int u, v; |
| cin >> u >> v; |
| out[u].push_back(v); |
| in[v].push_back(u); |
| } |
| |
| |
| vector<int> order(n); |
| iota(order.begin(), order.end(), 1); |
| mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()); |
| shuffle(order.begin(), order.end(), rng); |
| |
| |
| vector<int> nxt(n + 1, -1), prv(n + 1, -1); |
| vector<char> vis(n + 1, 0); |
| vector<int> posOut(n + 1, 0), posIn(n + 1, 0); |
| vector<int> comp(n + 1, -1); |
| vector<int> head_map(n + 1, -1), tail_map(n + 1, -1); |
| |
| |
| vector<int> headOf, tailOf, sizeOfPath, parent; |
| vector<char> active; |
| headOf.reserve(n); |
| tailOf.reserve(n); |
| sizeOfPath.reserve(n); |
| parent.reserve(n); |
| active.reserve(n); |
| |
| auto findp = [&](int x) { |
| int r = x; |
| while (parent[r] != r) r = parent[r]; |
| while (parent[x] != x) { |
| int p = parent[x]; |
| parent[x] = r; |
| x = p; |
| } |
| return r; |
| }; |
| |
| |
| int path_count = 0; |
| for (int s : order) { |
| if (vis[s]) continue; |
| deque<int> dq; |
| dq.push_back(s); |
| vis[s] = 1; |
| int head = s, tail = s; |
| while (true) { |
| bool extended = false; |
| |
| while (true) { |
| int u = tail; |
| int &p = posOut[u]; |
| while (p < (int)out[u].size() && vis[out[u][p]]) ++p; |
| if (p >= (int)out[u].size()) break; |
| int w = out[u][p++]; |
| dq.push_back(w); |
| vis[w] = 1; |
| tail = w; |
| extended = true; |
| } |
| |
| while (true) { |
| int u = head; |
| int &p = posIn[u]; |
| while (p < (int)in[u].size() && vis[in[u][p]]) ++p; |
| if (p >= (int)in[u].size()) break; |
| int w = in[u][p++]; |
| dq.push_front(w); |
| vis[w] = 1; |
| head = w; |
| extended = true; |
| } |
| if (!extended) break; |
| } |
| |
| if (!dq.empty()) { |
| for (size_t i = 0; i + 1 < dq.size(); ++i) { |
| int u = dq[i], v = dq[i + 1]; |
| nxt[u] = v; |
| prv[v] = u; |
| } |
| int pid = path_count++; |
| headOf.push_back(head); |
| tailOf.push_back(tail); |
| sizeOfPath.push_back((int)dq.size()); |
| parent.push_back(pid); |
| active.push_back(1); |
| head_map[head] = pid; |
| tail_map[tail] = pid; |
| for (int x : dq) comp[x] = pid; |
| } |
| } |
| |
| |
| function<int(int)> Find = [&](int x)->int { |
| if (parent[x] == x) return x; |
| parent[x] = Find(parent[x]); |
| return parent[x]; |
| }; |
| |
| |
| queue<int> q; |
| for (int i = 0; i < path_count; ++i) q.push(i); |
| |
| while (!q.empty()) { |
| int pid = q.front(); q.pop(); |
| int rep = Find(pid); |
| if (!active[rep]) continue; |
| int u = tailOf[rep]; |
| if (u == -1) continue; |
| bool merged = false; |
| for (int v : out[u]) { |
| int pid2 = head_map[v]; |
| if (pid2 == -1) continue; |
| int rep2 = Find(pid2); |
| rep = Find(rep); |
| if (!active[rep] || !active[rep2]) continue; |
| if (rep2 == rep) continue; |
| |
| |
| |
| nxt[u] = v; |
| prv[v] = u; |
| |
| int big = (sizeOfPath[rep] >= sizeOfPath[rep2]) ? rep : rep2; |
| int small = (big == rep ? rep2 : rep); |
| parent[small] = big; |
| int newHead = headOf[rep]; |
| int newTail = tailOf[rep2]; |
| headOf[big] = newHead; |
| tailOf[big] = newTail; |
| sizeOfPath[big] = sizeOfPath[rep] + sizeOfPath[rep2]; |
| active[small] = 0; |
| |
| head_map[v] = -1; |
| head_map[newHead] = big; |
| tail_map[u] = -1; |
| tail_map[newTail] = big; |
| |
| int cur = headOf[small]; |
| while (cur != -1) { |
| comp[cur] = big; |
| if (cur == tailOf[small]) break; |
| cur = nxt[cur]; |
| } |
| q.push(big); |
| merged = true; |
| break; |
| } |
| (void)merged; |
| } |
| |
| |
| int bestRep = -1, bestSize = -1; |
| for (int i = 0; i < path_count; ++i) { |
| int rep = Find(i); |
| if (!active[rep]) continue; |
| if (sizeOfPath[rep] > bestSize) { |
| bestSize = sizeOfPath[rep]; |
| bestRep = rep; |
| } |
| } |
| if (bestRep == -1) { |
| |
| cout << 1 << "\n1\n"; |
| return 0; |
| } |
| |
| |
| vector<int> ans; |
| ans.reserve(sizeOfPath[bestRep]); |
| int cur = headOf[bestRep]; |
| while (cur != -1) { |
| ans.push_back(cur); |
| if (cur == tailOf[bestRep]) break; |
| cur = nxt[cur]; |
| } |
| |
| cout << (int)ans.size() << "\n"; |
| for (size_t i = 0; i < ans.size(); ++i) { |
| if (i) cout << ' '; |
| cout << ans[i]; |
| } |
| cout << "\n"; |
| return 0; |
| } |