File size: 4,603 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
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>

using namespace std;

// Maximum number of vertices as per constraints
const int MAXN = 500005;

// Graph and degree information
vector<int> adj[MAXN];
int in_degree[MAXN];
int out_degree[MAXN];

// Visited array for DFS
bool visited[MAXN];
// To keep track of the current neighbor index for each node during iterative DFS
int cur_edge[MAXN]; 

// Path storage
vector<int> best_path;
vector<int> current_path;

int n, m;
vector<int> a(10); // Scoring parameters (unused in logic)

// Comparator to sort neighbors:
// 1. Prefer neighbors with lower in-degree (harder to reach later)
// 2. Prefer neighbors that are not dead ends (out-degree > 0)
// 3. Prefer neighbors with lower out-degree (Warnsdorff's heuristic)
bool compareNeighbors(int u, int v) {
    if (in_degree[u] != in_degree[v])
        return in_degree[u] < in_degree[v];
    
    bool term_u = (out_degree[u] == 0);
    bool term_v = (out_degree[v] == 0);
    if (term_u != term_v) return !term_u; // Non-terminal nodes come first
    
    return out_degree[u] < out_degree[v];
}

// Comparator for choosing start nodes
bool compareStartNodes(int u, int v) {
    if (in_degree[u] != in_degree[v])
        return in_degree[u] < in_degree[v];
    return out_degree[u] < out_degree[v];
}

int main() {
    // Optimize I/O operations
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    if (!(cin >> n >> m)) return 0;
    
    for (int i = 0; i < 10; ++i) cin >> a[i];

    for (int i = 0; i < m; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        out_degree[u]++;
        in_degree[v]++;
    }

    // Sort adjacency lists based on heuristic
    for (int i = 1; i <= n; ++i) {
        sort(adj[i].begin(), adj[i].end(), compareNeighbors);
    }

    // Identify potential start nodes
    vector<int> start_nodes;
    start_nodes.reserve(n);
    for (int i = 1; i <= n; ++i) {
        start_nodes.push_back(i);
    }
    
    sort(start_nodes.begin(), start_nodes.end(), compareStartNodes);

    // Heuristic: if nodes with in-degree 0 exist, start must be one of them.
    // Otherwise, try a few best candidates.
    int candidates_to_try = min(n, 20); 
    int zero_in_count = 0;
    for(int u : start_nodes) if(in_degree[u] == 0) zero_in_count++;
    if(zero_in_count > 0) candidates_to_try = zero_in_count; 

    // Time management
    clock_t start_time = clock();
    double time_limit = 3.8; 
    long long operations = 0;
    
    for (int k = 0; k < candidates_to_try; ++k) {
        int start_node = start_nodes[k];
        
        current_path.clear();
        current_path.reserve(n);
        
        // Initialize DFS from start_node
        current_path.push_back(start_node);
        visited[start_node] = true;
        cur_edge[start_node] = 0;
        
        if (current_path.size() > best_path.size()) {
            best_path = current_path;
        }

        // Iterative DFS
        while (!current_path.empty()) {
            operations++;
            // Check time limit periodically
            if ((operations & 65535) == 0) {
                if ((double)(clock() - start_time) / CLOCKS_PER_SEC > time_limit) goto end_search;
            }

            int u = current_path.back();
            
            // If Hamiltonian path found
            if (current_path.size() == n) {
                best_path = current_path;
                goto end_search; 
            }
            
            bool found = false;
            // Try to find an unvisited neighbor
            while (cur_edge[u] < adj[u].size()) {
                int v = adj[u][cur_edge[u]];
                cur_edge[u]++;
                if (!visited[v]) {
                    visited[v] = true;
                    current_path.push_back(v);
                    cur_edge[v] = 0; // Reset iterator for the new node
                    found = true;
                    if (current_path.size() > best_path.size()) {
                        best_path = current_path;
                    }
                    break; // Successfully pushed a neighbor
                }
            }

            if (!found) {
                // Backtrack
                visited[u] = false;
                cur_edge[u] = 0; // Reset iterator for future visits
                current_path.pop_back();
            }
        }
    }

end_search:
    cout << best_path.size() << "\n";
    for (int i = 0; i < best_path.size(); ++i) {
        cout << best_path[i] << (i == best_path.size() - 1 ? "" : " ");
    }
    cout << "\n";

    return 0;
}