| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| struct FastScanner { |
| static const int BUFSIZE = 1 << 20; |
| int idx = 0, sz = 0; |
| char buf[BUFSIZE]; |
| inline char gc() { |
| if (idx >= sz) { sz = (int)fread(buf, 1, BUFSIZE, stdin); idx = 0; if (!sz) return 0; } |
| return buf[idx++]; |
| } |
| template<class T> bool readInt(T &out) { |
| char c; T sign = 1; out = 0; |
| do { c = gc(); if (!c) return false; } while (c <= ' '); |
| if (c == '-') { sign = -1; c = gc(); } |
| for (; c >= '0' && c <= '9'; c = gc()) out = out * 10 + (c - '0'); |
| out *= sign; |
| return true; |
| } |
| } fs; |
|
|
| static uint64_t rngState; |
| static inline uint64_t splitmix64() { |
| uint64_t x = (rngState += 0x9e3779b97f4a7c15ULL); |
| x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL; |
| x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL; |
| return x ^ (x >> 31); |
| } |
| static inline int randInt(int n) { return (int)(splitmix64() % n); } |
|
|
| chrono::high_resolution_clock::time_point t0; |
| inline double elapsed() { |
| return chrono::duration<double>(chrono::high_resolution_clock::now() - t0).count(); |
| } |
|
|
| int n, m; |
| int *adjData, *radjData; |
| int *adjStart, *radjStart; |
| int *degOut, *degIn; |
| int *adjSorted; |
|
|
| inline bool hasEdge(int u, int v) { |
| return binary_search(adjSorted + adjStart[u], adjSorted + adjStart[u] + degOut[u], v); |
| } |
|
|
| vector<int> bestPath; |
|
|
| void improvePath(vector<int>& path, double timeLim) { |
| if (path.empty() || (int)path.size() == n) return; |
|
|
| int *nxt = (int*)calloc(n + 1, sizeof(int)); |
| int *prv = (int*)calloc(n + 1, sizeof(int)); |
| char *used = (char*)calloc(n + 1, sizeof(char)); |
|
|
| for (int v : path) used[v] = 1; |
| for (int i = 0; i + 1 < (int)path.size(); i++) { |
| nxt[path[i]] = path[i + 1]; |
| prv[path[i + 1]] = path[i]; |
| } |
| int head = path[0], tail = path.back(); |
|
|
| auto extendEnds = [&]() { |
| while (true) { |
| bool prog = false; |
| while (true) { |
| int best = 0; |
| int s = adjStart[tail], l = degOut[tail]; |
| for (int j = 0; j < l; j++) if (!used[adjData[s + j]]) { best = adjData[s + j]; break; } |
| if (!best) break; |
| nxt[tail] = best; prv[best] = tail; used[best] = 1; tail = best; prog = true; |
| } |
| while (true) { |
| int best = 0; |
| int s = radjStart[head], l = degIn[head]; |
| for (int j = 0; j < l; j++) if (!used[radjData[s + j]]) { best = radjData[s + j]; break; } |
| if (!best) break; |
| prv[head] = best; nxt[best] = head; used[best] = 1; head = best; prog = true; |
| } |
| if (!prog) break; |
| } |
| }; |
|
|
| auto insertionPass = [&]() -> bool { |
| bool changed = false; |
| int u = head; |
| while (u) { |
| int w = nxt[u]; |
| if (!w) break; |
| int s = adjStart[u], l = degOut[u]; |
| for (int j = 0; j < l; j++) { |
| int v = adjData[s + j]; |
| if (!used[v] && hasEdge(v, w)) { |
| nxt[u] = v; prv[v] = u; nxt[v] = w; prv[w] = v; |
| used[v] = 1; changed = true; w = v; |
| } |
| } |
| u = w; |
| } |
| return changed; |
| }; |
|
|
| auto reverseInsertion = [&]() -> bool { |
| bool changed = false; |
| for (int v = 1; v <= n; v++) { |
| if (used[v]) continue; |
| bool ins = false; |
| int s = adjStart[v], l = degOut[v]; |
| for (int j = 0; j < l && !ins; j++) { |
| int w = adjData[s + j]; |
| if (!used[w]) continue; |
| int u2 = prv[w]; |
| if (u2 && hasEdge(u2, v)) { |
| nxt[u2] = v; prv[v] = u2; nxt[v] = w; prv[w] = v; |
| used[v] = 1; changed = true; ins = true; |
| } |
| } |
| if (ins) continue; |
| int rs = radjStart[v], rl = degIn[v]; |
| for (int j = 0; j < rl && !ins; j++) { |
| int u2 = radjData[rs + j]; |
| if (!used[u2]) continue; |
| int w = nxt[u2]; |
| if (w && hasEdge(v, w)) { |
| nxt[u2] = v; prv[v] = u2; nxt[v] = w; prv[w] = v; |
| used[v] = 1; changed = true; ins = true; |
| } |
| } |
| if (ins) continue; |
| if (hasEdge(v, head)) { |
| prv[head] = v; nxt[v] = head; head = v; |
| used[v] = 1; changed = true; |
| } else if (hasEdge(tail, v)) { |
| nxt[tail] = v; prv[v] = tail; tail = v; |
| used[v] = 1; changed = true; |
| } |
| } |
| return changed; |
| }; |
|
|
| extendEnds(); |
| for (int pass = 0; pass < 30; pass++) { |
| bool ch = insertionPass(); |
| extendEnds(); |
| if (!ch) break; |
| } |
| for (int pass = 0; pass < 30 && elapsed() < timeLim; pass++) { |
| bool ch = reverseInsertion(); |
| extendEnds(); |
| insertionPass(); |
| extendEnds(); |
| if (!ch) break; |
| } |
|
|
| |
| if (n <= 1000 && elapsed() < timeLim) { |
| for (int pass = 0; pass < 5 && elapsed() < timeLim; pass++) { |
| bool changed = false; |
| for (int v1 = 1; v1 <= n && elapsed() < timeLim; v1++) { |
| if (used[v1]) continue; |
| bool done = false; |
| int s1 = adjStart[v1], l1 = degOut[v1]; |
| for (int j1 = 0; j1 < l1 && !done; j1++) { |
| int v2 = adjData[s1 + j1]; |
| if (used[v2] || v2 == v1) continue; |
| int rs1 = radjStart[v1], rl1 = degIn[v1]; |
| for (int j2 = 0; j2 < rl1 && !done; j2++) { |
| int u = radjData[rs1 + j2]; |
| if (!used[u]) continue; |
| int w = nxt[u]; |
| if (w && hasEdge(v2, w)) { |
| nxt[u] = v1; prv[v1] = u; |
| nxt[v1] = v2; prv[v2] = v1; |
| nxt[v2] = w; prv[w] = v2; |
| used[v1] = 1; used[v2] = 1; |
| changed = true; done = true; |
| } |
| } |
| |
| if (!done && hasEdge(v2, head)) { |
| int rs2 = radjStart[v1], rl2 = degIn[v1]; |
| |
| |
| |
| nxt[v1] = v2; prv[v2] = v1; nxt[v2] = head; prv[head] = v2; |
| head = v1; |
| used[v1] = 1; used[v2] = 1; |
| changed = true; done = true; |
| } |
| if (!done && hasEdge(tail, v1)) { |
| nxt[tail] = v1; prv[v1] = tail; nxt[v1] = v2; prv[v2] = v1; |
| tail = v2; |
| used[v1] = 1; used[v2] = 1; |
| changed = true; done = true; |
| } |
| } |
| } |
| extendEnds(); |
| insertionPass(); |
| reverseInsertion(); |
| extendEnds(); |
| if (!changed) break; |
| } |
| } |
|
|
| |
| if (n <= 1000 && elapsed() < timeLim) { |
| for (int pass = 0; pass < 5 && elapsed() < timeLim; pass++) { |
| bool changed = false; |
| int u = head; |
| while (u && elapsed() < timeLim) { |
| int w = nxt[u]; |
| if (!w) break; |
| int s = adjStart[u], l = degOut[u]; |
| bool rerouted = false; |
| for (int j = 0; j < l && !rerouted; j++) { |
| int v = adjData[s + j]; |
| if (v == w || used[v]) continue; |
| if (hasEdge(v, w)) { |
| nxt[u] = v; prv[v] = u; nxt[v] = w; prv[w] = v; |
| used[v] = 1; changed = true; rerouted = true; |
| } |
| } |
| if (!rerouted) { |
| |
| for (int j1 = 0; j1 < l && !rerouted; j1++) { |
| int v1 = adjData[s + j1]; |
| if (v1 == w || used[v1]) continue; |
| int s2 = adjStart[v1], l2 = degOut[v1]; |
| for (int j2 = 0; j2 < l2 && !rerouted; j2++) { |
| int v2 = adjData[s2 + j2]; |
| if (v2 == w || v2 == v1 || used[v2]) continue; |
| if (hasEdge(v2, w)) { |
| nxt[u] = v1; prv[v1] = u; |
| nxt[v1] = v2; prv[v2] = v1; |
| nxt[v2] = w; prv[w] = v2; |
| used[v1] = 1; used[v2] = 1; |
| changed = true; rerouted = true; |
| } |
| } |
| } |
| } |
| u = nxt[u]; |
| } |
| extendEnds(); |
| insertionPass(); |
| reverseInsertion(); |
| extendEnds(); |
| if (!changed) break; |
| } |
| } |
|
|
| |
| |
| if (n <= 500 && elapsed() < timeLim) { |
| for (int pass = 0; pass < 3 && elapsed() < timeLim; pass++) { |
| bool changed = false; |
| for (int v = 1; v <= n && elapsed() < timeLim; v++) { |
| if (used[v]) continue; |
| |
| |
| |
| for (int b = 1; b <= n; b++) { |
| if (!used[b]) continue; |
| int pb = prv[b], nb = nxt[b]; |
| if (!pb && !nb) continue; |
|
|
| bool canReplace = false; |
| if (pb && nb) canReplace = hasEdge(pb, v) && hasEdge(v, nb); |
| else if (!pb && nb) canReplace = hasEdge(v, nb); |
| else if (pb && !nb) canReplace = hasEdge(pb, v); |
|
|
| if (!canReplace) continue; |
|
|
| |
| if (pb) nxt[pb] = v; else head = v; |
| if (nb) prv[nb] = v; else tail = v; |
| prv[v] = pb; nxt[v] = nb; |
| used[v] = 1; |
| used[b] = 0; prv[b] = 0; nxt[b] = 0; |
|
|
| |
| bool reins = false; |
| |
| for (int j = 0; j < degOut[b] && !reins; j++) { |
| int w = adjData[adjStart[b] + j]; |
| if (!used[w]) continue; |
| int pu = prv[w]; |
| if (pu && hasEdge(pu, b)) { |
| nxt[pu] = b; prv[b] = pu; nxt[b] = w; prv[w] = b; |
| used[b] = 1; reins = true; |
| } |
| } |
| if (!reins) { |
| for (int j = 0; j < degIn[b] && !reins; j++) { |
| int u2 = radjData[radjStart[b] + j]; |
| if (!used[u2]) continue; |
| int w = nxt[u2]; |
| if (w && hasEdge(b, w)) { |
| nxt[u2] = b; prv[b] = u2; nxt[b] = w; prv[w] = b; |
| used[b] = 1; reins = true; |
| } |
| } |
| } |
| if (!reins && hasEdge(b, head)) { |
| prv[head] = b; nxt[b] = head; head = b; |
| used[b] = 1; reins = true; |
| } |
| if (!reins && hasEdge(tail, b)) { |
| nxt[tail] = b; prv[b] = tail; tail = b; |
| used[b] = 1; reins = true; |
| } |
|
|
| if (reins) { |
| changed = true; |
| break; |
| } else { |
| |
| if (prv[v]) nxt[prv[v]] = b; else head = b; |
| if (nxt[v]) prv[nxt[v]] = b; else tail = b; |
| prv[b] = prv[v]; nxt[b] = nxt[v]; |
| used[b] = 1; |
| used[v] = 0; prv[v] = 0; nxt[v] = 0; |
| } |
| } |
| } |
| if (changed) { |
| extendEnds(); |
| insertionPass(); |
| reverseInsertion(); |
| extendEnds(); |
| } else break; |
| } |
| } |
|
|
| path.clear(); |
| for (int u = head; u; u = nxt[u]) { |
| path.push_back(u); |
| if ((int)path.size() > n) break; |
| } |
|
|
| free(nxt); free(prv); free(used); |
| } |
|
|
| vector<int> greedyPath(int start, int mode = 0) { |
| |
| char *used = (char*)calloc(n + 1, sizeof(char)); |
| deque<int> path; |
| path.push_back(start); |
| used[start] = 1; |
|
|
| while (true) { |
| bool prog = false; |
| while (true) { |
| int t = path.back(); |
| int best = 0; |
| int s = adjStart[t], l = degOut[t]; |
| if (mode == 1) { |
| int bestScore = INT_MAX; |
| for (int j = 0; j < l; j++) { |
| int v = adjData[s + j]; |
| if (!used[v]) { |
| int cnt = 0; |
| int vs = adjStart[v], vl = degOut[v]; |
| for (int k = 0; k < vl; k++) if (!used[adjData[vs + k]]) cnt++; |
| if (cnt < bestScore) { bestScore = cnt; best = v; } |
| } |
| } |
| } else if (mode == 2) { |
| |
| int cnt = 0; |
| for (int j = 0; j < l; j++) if (!used[adjData[s + j]]) cnt++; |
| if (cnt > 0) { |
| int pick = randInt(cnt), k = 0; |
| for (int j = 0; j < l; j++) if (!used[adjData[s + j]]) { if (k == pick) { best = adjData[s + j]; break; } k++; } |
| } |
| } else { |
| for (int j = 0; j < l; j++) if (!used[adjData[s + j]]) { best = adjData[s + j]; break; } |
| } |
| if (!best) break; |
| path.push_back(best); used[best] = 1; prog = true; |
| } |
| while (true) { |
| int h = path.front(); |
| int best = 0; |
| int s = radjStart[h], l = degIn[h]; |
| if (mode == 1) { |
| int bestScore = INT_MAX; |
| for (int j = 0; j < l; j++) { |
| int u = radjData[s + j]; |
| if (!used[u]) { |
| int cnt = 0; |
| int us = radjStart[u], ul = degIn[u]; |
| for (int k = 0; k < ul; k++) if (!used[radjData[us + k]]) cnt++; |
| if (cnt < bestScore) { bestScore = cnt; best = u; } |
| } |
| } |
| } else if (mode == 2) { |
| int cnt = 0; |
| for (int j = 0; j < l; j++) if (!used[radjData[s + j]]) cnt++; |
| if (cnt > 0) { |
| int pick = randInt(cnt), k = 0; |
| for (int j = 0; j < l; j++) if (!used[radjData[s + j]]) { if (k == pick) { best = radjData[s + j]; break; } k++; } |
| } |
| } else { |
| for (int j = 0; j < l; j++) if (!used[radjData[s + j]]) { best = radjData[s + j]; break; } |
| } |
| if (!best) break; |
| path.push_front(best); used[best] = 1; prog = true; |
| } |
| if (!prog) break; |
| } |
|
|
| vector<int> result(path.begin(), path.end()); |
| free(used); |
| return result; |
| } |
|
|
| bool dfsBacktrackFrom(int start, double timeLim, bool randomize = false) { |
| char *used = (char*)calloc(n + 1, sizeof(char)); |
| int *pathArr = (int*)malloc(n * sizeof(int)); |
| int maxDeg = 0; |
| for (int u = 1; u <= n; u++) if (degOut[u] > maxDeg) maxDeg = degOut[u]; |
| int *nbrBuf = (int*)malloc((long long)n * (maxDeg + 1) * sizeof(int)); |
| int *nbrCnt = (int*)malloc(n * sizeof(int)); |
| int *nbrIdx = (int*)malloc(n * sizeof(int)); |
| pair<int,int> *tmp = (pair<int,int>*)malloc((maxDeg + 1) * sizeof(pair<int,int>)); |
| bool found = false; |
|
|
| int depth = 0; |
| pathArr[0] = start; |
| used[start] = 1; |
|
|
| auto computeNbrs = [&](int d) { |
| int v = pathArr[d]; |
| int s = adjStart[v], l = degOut[v]; |
| int tc = 0; |
| for (int j = 0; j < l; j++) { |
| int w = adjData[s + j]; |
| if (!used[w]) { |
| int sc = 0; |
| int ws = adjStart[w], wl = degOut[w]; |
| for (int k = 0; k < wl; k++) if (!used[adjData[ws + k]]) sc++; |
| if (randomize) sc = sc * 1000 + (int)(splitmix64() % 1000); |
| tmp[tc++] = {sc, w}; |
| } |
| } |
| sort(tmp, tmp + tc); |
| long long base = (long long)d * (maxDeg + 1); |
| for (int i = 0; i < tc; i++) nbrBuf[base + i] = tmp[i].second; |
| nbrCnt[d] = tc; |
| nbrIdx[d] = 0; |
| }; |
|
|
| computeNbrs(0); |
| long long checks = 0; |
|
|
| while (depth >= 0) { |
| if (++checks % 100000 == 0 && elapsed() > timeLim) break; |
|
|
| if (depth == n - 1) { |
| bestPath.assign(pathArr, pathArr + n); |
| found = true; |
| break; |
| } |
|
|
| if (depth + 1 > (int)bestPath.size()) { |
| bestPath.assign(pathArr, pathArr + depth + 1); |
| } |
|
|
| bool went_deeper = false; |
| long long base = (long long)depth * (maxDeg + 1); |
| while (nbrIdx[depth] < nbrCnt[depth]) { |
| int w = nbrBuf[base + nbrIdx[depth]]; |
| nbrIdx[depth]++; |
| if (used[w]) continue; |
| depth++; |
| pathArr[depth] = w; |
| used[w] = 1; |
| computeNbrs(depth); |
| went_deeper = true; |
| break; |
| } |
|
|
| if (!went_deeper) { |
| used[pathArr[depth]] = 0; |
| depth--; |
| } |
| } |
|
|
| free(used); free(pathArr); free(nbrBuf); free(nbrCnt); free(nbrIdx); free(tmp); |
| return found; |
| } |
|
|
| vector<int> dpOnOrder(const vector<int>& order) { |
| vector<int> pos(n + 1), dp(n + 1, 1), par(n + 1, 0); |
| for (int i = 0; i < n; i++) pos[order[i]] = i; |
| for (int i = 0; i < n; i++) { |
| int v = order[i]; |
| int s = adjStart[v], l = degOut[v]; |
| for (int j = 0; j < l; j++) { |
| int w = adjData[s + j]; |
| if (pos[w] > i && dp[v] + 1 > dp[w]) { |
| dp[w] = dp[v] + 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; } |
| vector<int> path; |
| int cur = bestV; |
| while (cur) { path.push_back(cur); cur = par[cur]; } |
| reverse(path.begin(), path.end()); |
| return path; |
| } |
|
|
| int main() { |
| rngState = chrono::high_resolution_clock::now().time_since_epoch().count(); |
| t0 = chrono::high_resolution_clock::now(); |
|
|
| fs.readInt(n); fs.readInt(m); |
| for (int i = 0; i < 10; i++) { int x; fs.readInt(x); } |
|
|
| adjStart = (int*)calloc(n + 1, sizeof(int)); |
| radjStart = (int*)calloc(n + 1, sizeof(int)); |
| degOut = (int*)calloc(n + 1, sizeof(int)); |
| degIn = (int*)calloc(n + 1, sizeof(int)); |
|
|
| int *edgeU = (int*)malloc(m * sizeof(int)); |
| int *edgeV = (int*)malloc(m * sizeof(int)); |
| for (int i = 0; i < m; i++) { |
| fs.readInt(edgeU[i]); fs.readInt(edgeV[i]); |
| degOut[edgeU[i]]++; |
| degIn[edgeV[i]]++; |
| } |
|
|
| for (int u = 1; u <= n; u++) { |
| adjStart[u] = (u == 1) ? 0 : adjStart[u - 1] + degOut[u - 1]; |
| radjStart[u] = (u == 1) ? 0 : radjStart[u - 1] + degIn[u - 1]; |
| } |
|
|
| adjData = (int*)malloc(m * sizeof(int)); |
| radjData = (int*)malloc(m * sizeof(int)); |
| { |
| int *ac = (int*)malloc((n + 1) * sizeof(int)); |
| int *rc = (int*)malloc((n + 1) * sizeof(int)); |
| for (int u = 1; u <= n; u++) { ac[u] = adjStart[u]; rc[u] = radjStart[u]; } |
| for (int i = 0; i < m; i++) { |
| adjData[ac[edgeU[i]]++] = edgeV[i]; |
| radjData[rc[edgeV[i]]++] = edgeU[i]; |
| } |
| free(ac); free(rc); |
| } |
| free(edgeU); free(edgeV); |
|
|
| adjSorted = (int*)malloc(m * sizeof(int)); |
| memcpy(adjSorted, adjData, m * sizeof(int)); |
| for (int u = 1; u <= n; u++) { |
| sort(adjSorted + adjStart[u], adjSorted + adjStart[u] + degOut[u]); |
| } |
|
|
| if (n <= 200) { |
| |
|
|
| |
| { |
| vector<pair<int,int>> starts; |
| for (int u = 1; u <= n; u++) starts.push_back({-(degOut[u] - degIn[u]), u}); |
| sort(starts.begin(), starts.end()); |
|
|
| bool found = false; |
| for (int i = 0; i < (int)starts.size() && elapsed() < 0.8 && !found; i++) { |
| double rem = 0.8 - elapsed(); |
| double t = max(rem / ((int)starts.size() - i), 0.01); |
| found = dfsBacktrackFrom(starts[i].second, elapsed() + t, false); |
| } |
|
|
| |
| if (!found) { |
| while (elapsed() < 2.0 && (int)bestPath.size() < n) { |
| int sv = randInt(n) + 1; |
| found = dfsBacktrackFrom(sv, elapsed() + 0.1, true); |
| if (found) break; |
| } |
| } |
| } |
|
|
| |
| if ((int)bestPath.size() >= n * 3 / 4 && (int)bestPath.size() < n) { |
| improvePath(bestPath, min(elapsed() + 1.0, 3.0)); |
| } |
|
|
| if ((int)bestPath.size() < n) { |
| |
| for (int s = 1; s <= n && elapsed() < 2.5; s++) { |
| auto path = greedyPath(s, 1); |
| if ((int)path.size() > (int)bestPath.size()) bestPath = move(path); |
| if ((int)bestPath.size() == n) break; |
| } |
| } |
|
|
| if ((int)bestPath.size() < n) { |
| |
| while (elapsed() < 3.0 && (int)bestPath.size() < n) { |
| for (int u = 1; u <= n; u++) { |
| int s = adjStart[u], l = degOut[u]; |
| for (int i = l - 1; i > 0; i--) { int j = splitmix64() % (i + 1); swap(adjData[s + i], adjData[s + j]); } |
| s = radjStart[u]; l = degIn[u]; |
| for (int i = l - 1; i > 0; i--) { int j = splitmix64() % (i + 1); swap(radjData[s + i], radjData[s + j]); } |
| } |
| int sv = randInt(n) + 1; |
| auto path = greedyPath(sv, 2); |
| if ((int)path.size() > (int)bestPath.size()) bestPath = move(path); |
| if ((int)bestPath.size() == n) break; |
| path = greedyPath(sv, 0); |
| if ((int)path.size() > (int)bestPath.size()) bestPath = move(path); |
| } |
| } |
|
|
| |
| if ((int)bestPath.size() < n && !bestPath.empty()) |
| improvePath(bestPath, 3.8); |
|
|
| } else { |
| |
| { |
| vector<int> order(n); |
| for (int i = 0; i < n; i++) order[i] = i + 1; |
| auto tryOrder = [&](vector<int>& ord) { |
| auto path = dpOnOrder(ord); |
| if ((int)path.size() > (int)bestPath.size()) bestPath = path; |
| }; |
|
|
| sort(order.begin(), order.end(), [&](int x, int y) { |
| int a = degOut[x] - degIn[x], b = degOut[y] - degIn[y]; |
| return a != b ? a > b : x < y; |
| }); |
| tryOrder(order); |
| sort(order.begin(), order.end(), [&](int x, int y) { |
| return degOut[x] != degOut[y] ? degOut[x] > degOut[y] : x < y; |
| }); |
| tryOrder(order); |
| for (int iter = 0; elapsed() < 1.0 && (int)bestPath.size() < n; iter++) { |
| for (size_t i = n - 1; i > 0; --i) { size_t j = splitmix64() % (i + 1); swap(order[i], order[j]); } |
| tryOrder(order); |
| } |
| } |
|
|
| if ((int)bestPath.size() < n && !bestPath.empty()) |
| improvePath(bestPath, 1.5); |
|
|
| { |
| vector<int> starts; |
| int best = 1; |
| for (int u = 2; u <= n; u++) if (degOut[u] - degIn[u] > degOut[best] - degIn[best]) best = u; |
| starts.push_back(best); |
| best = 1; |
| for (int u = 2; u <= n; u++) if (degIn[u] < degIn[best]) best = u; |
| starts.push_back(best); |
| for (int i = 0; i < 50; i++) starts.push_back(randInt(n) + 1); |
|
|
| for (int s : starts) { |
| if (elapsed() > 2.5 || (int)bestPath.size() == n) break; |
| auto path = greedyPath(s, 1); |
| if ((int)path.size() > (int)bestPath.size()) bestPath = move(path); |
| if ((int)bestPath.size() == n) break; |
| path = greedyPath(s, 0); |
| if ((int)path.size() > (int)bestPath.size()) bestPath = move(path); |
| } |
| } |
|
|
| if ((int)bestPath.size() < n && !bestPath.empty()) |
| improvePath(bestPath, 3.0); |
|
|
| if ((int)bestPath.size() < n) { |
| while (elapsed() < 3.5 && (int)bestPath.size() < n) { |
| for (int u = 1; u <= n; u++) { |
| int s = adjStart[u], l = degOut[u]; |
| for (int i = l - 1; i > 0; i--) { int j = splitmix64() % (i + 1); swap(adjData[s + i], adjData[s + j]); } |
| s = radjStart[u]; l = degIn[u]; |
| for (int i = l - 1; i > 0; i--) { int j = splitmix64() % (i + 1); swap(radjData[s + i], radjData[s + j]); } |
| } |
| auto path = greedyPath(randInt(n) + 1, 0); |
| if ((int)path.size() > (int)bestPath.size()) { |
| bestPath = move(path); |
| if ((int)bestPath.size() < n) improvePath(bestPath, min(elapsed() + 0.3, 3.7)); |
| } |
| } |
| } |
| } |
|
|
| if (bestPath.empty()) bestPath.push_back(1); |
|
|
| printf("%d\n", (int)bestPath.size()); |
| for (int i = 0; i < (int)bestPath.size(); i++) { |
| if (i) putchar(' '); |
| printf("%d", bestPath[i]); |
| } |
| putchar('\n'); |
| return 0; |
| } |
|
|