| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| static inline uint64_t splitmix64(uint64_t x) { |
| x += 0x9e3779b97f4a7c15ULL; |
| x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL; |
| x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL; |
| return x ^ (x >> 31); |
| } |
|
|
| struct RNG { |
| uint64_t x; |
| RNG() { |
| uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count(); |
| x = splitmix64(seed); |
| } |
| uint64_t next() { return x = splitmix64(x); } |
| template<class It> |
| void shuffle(It first, It last) { |
| size_t n = last - first; |
| for (size_t i = n - 1; i > 0; --i) { |
| size_t j = (size_t)(next() % (i + 1)); |
| swap(*(first + i), *(first + j)); |
| } |
| } |
| }; |
| RNG rng; |
|
|
| int main() { |
| ios::sync_with_stdio(false); |
| cin.tie(nullptr); |
| int n, m; |
| if (!(cin >> n >> m)) { |
| return 0; |
| } |
| vector<int> a(10); |
| for (int i = 0; i < 10; ++i) cin >> a[i]; |
|
|
| 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); |
| } |
|
|
| |
| for (int u = 1; u <= n; ++u) { |
| sort(out[u].begin(), out[u].end()); |
| } |
|
|
| vector<int> degOut(n + 1), degIn(n + 1); |
| for (int u = 1; u <= n; ++u) { |
| degOut[u] = (int)out[u].size(); |
| degIn[u] = (int)in[u].size(); |
| } |
|
|
| vector<int> order(n); |
| for (int i = 0; i < n; ++i) order[i] = i + 1; |
| vector<int> pos(n + 1, 0); |
| vector<int> dp(n + 1), par(n + 1); |
|
|
| auto runDPWithOrder = [&](const vector<int>& ord, vector<int>& pathOut) { |
| for (int i = 0; i < n; ++i) pos[ord[i]] = i; |
| for (int i = 1; i <= n; ++i) { |
| dp[i] = 1; |
| par[i] = 0; |
| } |
| for (int i = 0; i < n; ++i) { |
| int v = ord[i]; |
| int dv = dp[v]; |
| const auto& nbrs = out[v]; |
| for (int w : nbrs) { |
| if (pos[w] > i) { |
| if (dv + 1 > dp[w]) { |
| dp[w] = dv + 1; |
| par[w] = v; |
| } |
| } |
| } |
| } |
| int bestV = 1, bestLen = dp[1]; |
| for (int v = 2; v <= n; ++v) { |
| if (dp[v] > bestLen) { |
| bestLen = dp[v]; |
| bestV = v; |
| } |
| } |
| pathOut.clear(); |
| pathOut.reserve(bestLen); |
| int cur = bestV; |
| while (cur != 0) { |
| pathOut.push_back(cur); |
| cur = par[cur]; |
| } |
| reverse(pathOut.begin(), pathOut.end()); |
| return bestLen; |
| }; |
|
|
| vector<int> bestPath, tmpPath; |
|
|
| |
| long long budget = 15000000LL; |
| long long sizeSum = (long long)n + (long long)m; |
| int T = (int)min(50LL, max(2LL, budget / max(1LL, sizeSum)) + 2LL); |
|
|
| for (int iter = 0; iter < T; ++iter) { |
| if (iter == 0) { |
| sort(order.begin(), order.end(), [&](int x, int y) { |
| int a = degOut[x] - degIn[x]; |
| int b = degOut[y] - degIn[y]; |
| if (a != b) return a > b; |
| return x < y; |
| }); |
| } else if (iter == 1) { |
| sort(order.begin(), order.end(), [&](int x, int y) { |
| if (degOut[x] != degOut[y]) return degOut[x] > degOut[y]; |
| return x < y; |
| }); |
| } else { |
| rng.shuffle(order.begin(), order.end()); |
| } |
| int len = runDPWithOrder(order, tmpPath); |
| if ((int)bestPath.size() < len) { |
| bestPath = tmpPath; |
| if ((int)bestPath.size() == n) break; |
| } |
| } |
|
|
| if (bestPath.empty()) { |
| |
| if (n >= 1) { |
| |
| bool found = false; |
| for (int u = 1; u <= n && !found; ++u) { |
| for (int v : out[u]) { |
| bestPath = {u, v}; |
| found = true; |
| break; |
| } |
| } |
| if (!found) bestPath = {1}; |
| } |
| } |
|
|
| |
| auto extendEnds = [&](vector<int>& path) { |
| vector<char> inPath(n + 1, 0); |
| for (int v : path) inPath[v] = 1; |
| deque<int> dq; |
| for (int v : path) dq.push_back(v); |
| while (true) { |
| bool progressed = false; |
| |
| while (true) { |
| int t = dq.back(); |
| bool found = false; |
| const auto& nb = out[t]; |
| for (int w : nb) { |
| if (!inPath[w]) { |
| inPath[w] = 1; |
| dq.push_back(w); |
| found = true; |
| break; |
| } |
| } |
| if (!found) break; |
| progressed = true; |
| if ((int)dq.size() == n) break; |
| } |
| if ((int)dq.size() == n) break; |
| |
| while (true) { |
| int h = dq.front(); |
| bool found = false; |
| const auto& nb = in[h]; |
| for (int u : nb) { |
| if (!inPath[u]) { |
| inPath[u] = 1; |
| dq.push_front(u); |
| found = true; |
| break; |
| } |
| } |
| if (!found) break; |
| progressed = true; |
| if ((int)dq.size() == n) break; |
| } |
| if (!progressed) break; |
| if ((int)dq.size() == n) break; |
| } |
| vector<int> res; |
| res.reserve(dq.size()); |
| for (int v : dq) res.push_back(v); |
| path.swap(res); |
| }; |
|
|
| extendEnds(bestPath); |
|
|
| |
| auto hasEdge = [&](int u, int v) -> bool { |
| const auto& vec = out[u]; |
| auto it = lower_bound(vec.begin(), vec.end(), v); |
| return it != vec.end() && *it == v; |
| }; |
|
|
| auto insertBridging = [&](vector<int>& path) { |
| int k = (int)path.size(); |
| vector<int> next(n + 1, -1), prev(n + 1, -1); |
| vector<char> inPath(n + 1, 0); |
| if (k == 0) return; |
| for (int i = 0; i < k; ++i) inPath[path[i]] = 1; |
| for (int i = 0; i + 1 < k; ++i) { |
| int u = path[i], v = path[i + 1]; |
| next[u] = v; |
| prev[v] = u; |
| } |
| int head = path[0], tail = path.back(); |
|
|
| deque<int> q; |
| vector<char> inQ(n + 1, 0); |
| for (int i = 0; i + 1 < k; ++i) { |
| int u = path[i]; |
| if (!inQ[u]) { q.push_back(u); inQ[u] = 1; } |
| } |
|
|
| while (!q.empty()) { |
| int p = q.front(); q.pop_front(); inQ[p] = 0; |
| int w = next[p]; |
| if (w == -1) continue; |
| bool insertedAny = false; |
| const auto& nbrs = out[p]; |
| for (int x : nbrs) { |
| if (inPath[x]) continue; |
| int curSucc = next[p]; |
| if (curSucc == -1) break; |
| if (hasEdge(x, curSucc)) { |
| |
| next[p] = x; |
| prev[x] = p; |
| next[x] = curSucc; |
| prev[curSucc] = x; |
| inPath[x] = 1; |
| insertedAny = true; |
|
|
| if (!inQ[x] && next[x] != -1) { q.push_back(x); inQ[x] = 1; } |
| } |
| } |
| if (insertedAny && next[p] != -1 && !inQ[p]) { q.push_back(p); inQ[p] = 1; } |
| } |
|
|
| |
| vector<int> res; |
| res.reserve(n); |
| int cur = head; |
| while (cur != -1) { |
| res.push_back(cur); |
| cur = next[cur]; |
| } |
| path.swap(res); |
| }; |
|
|
| insertBridging(bestPath); |
| if ((int)bestPath.size() < n) { |
| extendEnds(bestPath); |
| insertBridging(bestPath); |
| } |
|
|
| |
| if ((int)bestPath.size() < n) { |
| vector<char> used(n + 1, 0); |
| for (int v : bestPath) used[v] = 1; |
| vector<int> rest; |
| rest.reserve(n - bestPath.size()); |
| for (int v = 1; v <= n; ++v) if (!used[v]) rest.push_back(v); |
| if (!rest.empty()) rng.shuffle(rest.begin(), rest.end()); |
| vector<int> ordFinal; |
| ordFinal.reserve(n); |
| ordFinal.insert(ordFinal.end(), bestPath.begin(), bestPath.end()); |
| ordFinal.insert(ordFinal.end(), rest.begin(), rest.end()); |
|
|
| vector<int> trialPath; |
| int len = runDPWithOrder(ordFinal, trialPath); |
| if (len > (int)bestPath.size()) bestPath = trialPath; |
|
|
| |
| reverse(ordFinal.begin(), ordFinal.end()); |
| len = runDPWithOrder(ordFinal, trialPath); |
| if (len > (int)bestPath.size()) bestPath = trialPath; |
|
|
| extendEnds(bestPath); |
| insertBridging(bestPath); |
| extendEnds(bestPath); |
| } |
|
|
| |
| cout << bestPath.size() << "\n"; |
| for (size_t i = 0; i < bestPath.size(); ++i) { |
| if (i) cout << ' '; |
| cout << bestPath[i]; |
| } |
| cout << "\n"; |
| return 0; |
| } |