| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| |
| struct FastScanner { |
| static const int BUFSIZE = 1 << 20; |
| int idx = 0, size = 0; |
| char buf[BUFSIZE]; |
| inline char getChar() { |
| if (idx >= size) { |
| size = (int)fread(buf, 1, BUFSIZE, stdin); |
| idx = 0; |
| if (size == 0) return 0; |
| } |
| return buf[idx++]; |
| } |
| template <typename T> |
| bool nextInt(T &out) { |
| char c; T sign = 1; T val = 0; |
| c = getChar(); |
| if (!c) return false; |
| while (c != '-' && (c < '0' || c > '9')) { |
| c = getChar(); |
| if (!c) return false; |
| } |
| if (c == '-') { sign = -1; c = getChar(); } |
| for (; c >= '0' && c <= '9'; c = getChar()) val = val * 10 + (c - '0'); |
| out = val * sign; |
| return true; |
| } |
| } In; |
|
|
| int main() { |
| ios::sync_with_stdio(false); |
| cin.tie(nullptr); |
|
|
| int n, m; |
| if (!In.nextInt(n)) return 0; |
| In.nextInt(m); |
|
|
| |
| for (int i = 0; i < 10; ++i) { |
| int tmp; In.nextInt(tmp); |
| } |
|
|
| vector<vector<int>> outScan(n + 1), inScan(n + 1); |
| outScan.shrink_to_fit(); |
| inScan.shrink_to_fit(); |
|
|
| |
| for (int i = 0; i < m; ++i) { |
| int u, v; In.nextInt(u); In.nextInt(v); |
| if (u >= 1 && u <= n && v >= 1 && v <= n && u != v) { |
| outScan[u].push_back(v); |
| inScan[v].push_back(u); |
| } |
| } |
|
|
| |
| vector<vector<int>> outSorted(n + 1); |
| for (int u = 1; u <= n; ++u) { |
| outSorted[u] = outScan[u]; |
| sort(outSorted[u].begin(), outSorted[u].end()); |
| outSorted[u].erase(unique(outSorted[u].begin(), outSorted[u].end()), outSorted[u].end()); |
| } |
|
|
| auto hasEdge = [&](int u, int v) -> bool { |
| const auto &vec = outSorted[u]; |
| auto it = lower_bound(vec.begin(), vec.end(), v); |
| return (it != vec.end() && *it == v); |
| }; |
|
|
| vector<int> degOut(n + 1), degIn(n + 1); |
| for (int u = 1; u <= n; ++u) { |
| degOut[u] = (int)outScan[u].size(); |
| degIn[u] = (int)inScan[u].size(); |
| } |
|
|
| |
| auto runAttempt = [&](int start, int maxInsertionPasses) -> vector<int> { |
| vector<char> used(n + 1, 0); |
| vector<int> nxt(n + 1, 0), prv(n + 1, 0); |
| vector<int> outIter(n + 1, 0), inIter(n + 1, 0); |
|
|
| int head = start, tail = start; |
| used[start] = 1; |
|
|
| auto extendEnds = [&]() { |
| while (true) { |
| bool progressed = false; |
| |
| while (true) { |
| auto &vec = outScan[tail]; |
| int &pos = outIter[tail]; |
| while (pos < (int)vec.size() && used[vec[pos]]) pos++; |
| if (pos >= (int)vec.size()) break; |
| int v = vec[pos++]; |
| if (used[v]) continue; |
| nxt[tail] = v; |
| prv[v] = tail; |
| nxt[v] = 0; |
| used[v] = 1; |
| tail = v; |
| progressed = true; |
| } |
| |
| while (true) { |
| auto &vec = inScan[head]; |
| int &pos = inIter[head]; |
| while (pos < (int)vec.size() && used[vec[pos]]) pos++; |
| if (pos >= (int)vec.size()) break; |
| int u = vec[pos++]; |
| if (used[u]) continue; |
| prv[head] = u; |
| nxt[u] = head; |
| prv[u] = 0; |
| used[u] = 1; |
| head = u; |
| progressed = true; |
| } |
| if (!progressed) break; |
| } |
| }; |
|
|
| extendEnds(); |
|
|
| auto insertionPass = [&]() -> bool { |
| bool changed = false; |
| int u = head; |
| while (u != 0) { |
| int w = nxt[u]; |
| if (w == 0) break; |
| auto &neighbors = outScan[u]; |
| for (int id = 0; id < (int)neighbors.size(); ++id) { |
| int v = neighbors[id]; |
| if (!used[v] && hasEdge(v, w)) { |
| |
| nxt[u] = v; |
| prv[v] = u; |
| nxt[v] = w; |
| prv[w] = v; |
| used[v] = 1; |
| w = v; |
| changed = true; |
| } |
| } |
| u = w; |
| } |
| return changed; |
| }; |
|
|
| for (int pass = 0; pass < maxInsertionPasses; ++pass) { |
| bool ch = insertionPass(); |
| if (!ch) break; |
| extendEnds(); |
| } |
|
|
| |
| vector<int> ans; |
| ans.reserve(n); |
| for (int u = head; u != 0; u = nxt[u]) ans.push_back(u); |
| return ans; |
| }; |
|
|
| |
| int startMaxDegSum = 1, startMaxOut = 1, startMaxIn = 1; |
| for (int u = 2; u <= n; ++u) { |
| if (degOut[u] + degIn[u] > degOut[startMaxDegSum] + degIn[startMaxDegSum]) startMaxDegSum = u; |
| if (degOut[u] > degOut[startMaxOut]) startMaxOut = u; |
| if (degIn[u] > degIn[startMaxIn]) startMaxIn = u; |
| } |
|
|
| vector<int> starts; |
| auto push_unique = [&](int v) { |
| if (v < 1 || v > n) return; |
| for (int x : starts) if (x == v) return; |
| starts.push_back(v); |
| }; |
| push_unique(startMaxDegSum); |
| push_unique(startMaxOut); |
| push_unique(startMaxIn); |
|
|
| |
| std::mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count()); |
| int randomTrials = 5; |
| for (int i = 0; i < randomTrials; ++i) { |
| int v = (int)(rng() % n) + 1; |
| push_unique(v); |
| } |
|
|
| vector<int> bestPath; |
| size_t bestLen = 0; |
|
|
| |
| auto t0 = chrono::high_resolution_clock::now(); |
| const double timeBudget = 3.8; |
|
|
| for (size_t i = 0; i < starts.size(); ++i) { |
| auto t1 = chrono::high_resolution_clock::now(); |
| double elapsed = chrono::duration<double>(t1 - t0).count(); |
| if (elapsed > timeBudget) break; |
|
|
| int start = starts[i]; |
| vector<int> cand = runAttempt(start, 2); |
| if (cand.size() > bestLen) { |
| bestLen = cand.size(); |
| bestPath.swap(cand); |
| if (bestLen == (size_t)n) break; |
| } |
| } |
|
|
| if (bestPath.empty()) { |
| |
| bestPath.push_back(1); |
| } |
|
|
| cout << bestPath.size() << "\n"; |
| for (size_t i = 0; i < bestPath.size(); ++i) { |
| if (i) cout << ' '; |
| cout << bestPath[i]; |
| } |
| cout << "\n"; |
| return 0; |
| } |