File size: 4,932 Bytes
1fd0050 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | #include <iostream>
#include <vector>
#include <algorithm>
#include <random>
#include <ctime>
using namespace std;
// Global constants and arrays to store graph and state
const int MAXN = 500005;
vector<int> adj[MAXN];
int in_degree[MAXN];
int current_in_degree[MAXN];
int out_degree[MAXN];
bool visited[MAXN];
// Random number generator
mt19937 rng(1337);
int main() {
// Fast I/O
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, m;
if (!(cin >> n >> m)) return 0;
// Consume scoring parameters
int temp;
for(int i=0; i<10; ++i) cin >> temp;
for(int i=0; i<m; ++i) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
out_degree[u]++;
in_degree[v]++;
}
// Identify potential start nodes (nodes with in-degree 0)
vector<int> start_candidates;
for(int i=1; i<=n; ++i) {
if(in_degree[i] == 0) {
start_candidates.push_back(i);
}
}
vector<int> best_path;
int max_len = 0;
clock_t start_time = clock();
double time_limit = 3.85; // Time limit safe margin (Total limit 4s)
while (true) {
// Check time limit
if ((double)(clock() - start_time) / CLOCKS_PER_SEC > time_limit) break;
// Restore state for the new run
for(int i=1; i<=n; ++i) {
current_in_degree[i] = in_degree[i];
visited[i] = false;
}
// Select start node
int curr;
if (!start_candidates.empty()) {
// If there are nodes with in-degree 0, the path must start at one of them
uniform_int_distribution<int> dist(0, start_candidates.size() - 1);
curr = start_candidates[dist(rng)];
} else {
// If no in-degree 0 nodes, pick random node
uniform_int_distribution<int> dist(1, n);
curr = dist(rng);
}
vector<int> current_path;
current_path.reserve(n);
visited[curr] = true;
current_path.push_back(curr);
// Update degrees for the start node
for(int v : adj[curr]) {
current_in_degree[v]--;
}
// Greedy DFS traversal
while((int)current_path.size() < n) {
// Heuristic:
// 1. Pick neighbor with lowest current_in_degree (most constrained)
// 2. Tie-breaker: Pick neighbor with highest out_degree (most options forward)
// 3. Tie-breaker: Random
int min_deg = 1e9;
vector<int> candidates;
for(int v : adj[curr]) {
if(!visited[v]) {
if(current_in_degree[v] < min_deg) {
min_deg = current_in_degree[v];
candidates.clear();
candidates.push_back(v);
} else if(current_in_degree[v] == min_deg) {
candidates.push_back(v);
}
}
}
if(candidates.empty()) break; // Stuck
int next_node = -1;
if(candidates.size() == 1) {
next_node = candidates[0];
} else {
// Secondary filter: max out_degree
int max_out = -1;
vector<int> best_candidates;
for(int v : candidates) {
if(out_degree[v] > max_out) {
max_out = out_degree[v];
best_candidates.clear();
best_candidates.push_back(v);
} else if(out_degree[v] == max_out) {
best_candidates.push_back(v);
}
}
if(best_candidates.size() == 1) {
next_node = best_candidates[0];
} else {
uniform_int_distribution<int> dist(0, best_candidates.size() - 1);
next_node = best_candidates[dist(rng)];
}
}
curr = next_node;
visited[curr] = true;
current_path.push_back(curr);
// Update degrees for the chosen node
for(int v : adj[curr]) {
if(!visited[v]) {
current_in_degree[v]--;
}
}
}
if((int)current_path.size() > max_len) {
max_len = current_path.size();
best_path = current_path;
}
if(max_len == n) break; // Found a Hamiltonian 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";
return 0;
} |