Pagini recente » Cod sursa (job #3313580) | Cod sursa (job #927337) | Cod sursa (job #522785) | Cod sursa (job #3313889) | Cod sursa (job #3358618)
#include <bits/stdc++.h>
using namespace std;
ifstream fin("santa.in");
ofstream fout("santa.out");
int n, m, S, E, Q;
vector<int> adj[45005];
int dfn[45005], low[45005], timer;
stack<pair<int, int>> st;
int num_bcc;
vector<int> bcc_nodes[45005];
vector<int> bct_adj[90005];
int dp_bcc[1 << 16];
int p_bcc[1 << 16][16];
void dfs(int u, int p = 0) {
dfn[u] = low[u] = ++timer;
for (int v : adj[u]) {
if (v == p) continue;
if (dfn[v]) {
low[u] = min(low[u], dfn[v]);
if (dfn[v] < dfn[u]) {
st.push({u, v});
}
} else {
st.push({u, v});
dfs(v, u);
low[u] = min(low[u], low[v]);
if (low[v] >= dfn[u]) {
num_bcc++;
while (true) {
auto edge = st.top();
st.pop();
bcc_nodes[num_bcc].push_back(edge.first);
bcc_nodes[num_bcc].push_back(edge.second);
if (edge == make_pair(u, v)) break;
}
sort(bcc_nodes[num_bcc].begin(), bcc_nodes[num_bcc].end());
bcc_nodes[num_bcc].erase(unique(bcc_nodes[num_bcc].begin(), bcc_nodes[num_bcc].end()), bcc_nodes[num_bcc].end());
}
}
}
}
bool has_edge(int u, int v) {
auto it = lower_bound(adj[u].begin(), adj[u].end(), v);
return it != adj[u].end() && *it == v;
}
vector<int> get_hamiltonian_path(int bcc_idx, int start_node, int end_node) {
vector<int>& V_bcc = bcc_nodes[bcc_idx];
int K = V_bcc.size();
if (K > 16) return {};
int start_idx = -1, end_idx = -1;
for (int i = 0; i < K; i++) {
if (V_bcc[i] == start_node) start_idx = i;
if (V_bcc[i] == end_node) end_idx = i;
}
if (start_idx == -1) return {};
if (end_node != -1 && end_idx == -1) return {};
int adj_mask[16] = {0};
for (int i = 0; i < K; i++) {
for (int j = 0; j < K; j++) {
if (i != j && has_edge(V_bcc[i], V_bcc[j])) {
adj_mask[i] |= (1 << j);
}
}
}
int max_mask = 1 << K;
for (int i = 0; i < max_mask; i++) dp_bcc[i] = 0;
dp_bcc[1 << start_idx] |= (1 << start_idx);
for (int mask = 0; mask < max_mask; mask++) {
int valid_u = dp_bcc[mask];
while (valid_u) {
int u = __builtin_ctz(valid_u);
valid_u &= valid_u - 1;
int available = adj_mask[u] & ~mask;
while (available) {
int v = __builtin_ctz(available);
available &= available - 1;
int next_mask = mask | (1 << v);
if (!(dp_bcc[next_mask] & (1 << v))) {
dp_bcc[next_mask] |= (1 << v);
p_bcc[next_mask][v] = u;
}
}
}
}
int target_mask = max_mask - 1;
int last = -1;
if (end_node != -1) {
if (dp_bcc[target_mask] & (1 << end_idx)) {
last = end_idx;
}
} else {
if (dp_bcc[target_mask]) {
last = __builtin_ctz(dp_bcc[target_mask]);
}
}
if (last == -1) return {};
vector<int> path;
int curr_mask = target_mask;
int curr_node = last;
while (curr_mask) {
path.push_back(V_bcc[curr_node]);
if (curr_mask == (1 << curr_node)) break;
int prev_node = p_bcc[curr_mask][curr_node];
curr_mask ^= (1 << curr_node);
curr_node = prev_node;
}
reverse(path.begin(), path.end());
return path;
}
bool solve_chain(vector<int> bcc_seq, vector<int> cut_seq, vector<int>& final_path) {
if (bcc_seq.empty()) {
if (Q == S) {
final_path = {S};
return true;
}
return false;
}
int k = bcc_seq.size();
int first_bcc = bcc_seq[0] - n;
bool q_in_first = false;
for (int x : bcc_nodes[first_bcc]) {
if (x == Q) q_in_first = true;
}
if (!q_in_first) return false;
vector<int> path;
for (int i = 0; i < k; i++) {
int C_idx = bcc_seq[i] - n;
int start_node = (i == 0) ? Q : cut_seq[i - 1];
int end_node = (i == k - 1) ? -1 : cut_seq[i];
vector<int> p = get_hamiltonian_path(C_idx, start_node, end_node);
if (p.empty()) return false;
if (i == 0) {
path = p;
} else {
for (int j = 1; j < p.size(); j++) {
path.push_back(p[j]);
}
}
}
final_path = path;
return true;
}
int main() {
fin >> n >> m;
for (int i = 1; i <= m; i++) {
int u, v;
fin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
fin >> S >> E >> Q;
for (int i = 1; i <= n; i++) {
sort(adj[i].begin(), adj[i].end());
}
for (int i = 1; i <= n; i++) {
if (!dfn[i]) dfs(i);
}
for (int i = 1; i <= num_bcc; i++) {
for (int u : bcc_nodes[i]) {
bct_adj[u].push_back(n + i);
bct_adj[n + i].push_back(u);
}
}
queue<int> q;
vector<int> bct_parent(n + num_bcc + 1, 0);
vector<bool> vis(n + num_bcc + 1, false);
q.push(S);
vis[S] = true;
while (!q.empty()) {
int u = q.front();
q.pop();
if (u == E) break;
for (int v : bct_adj[u]) {
if (!vis[v]) {
vis[v] = true;
bct_parent[v] = u;
q.push(v);
}
}
}
if (!vis[E] && S != E) {
fout << "No chance\n";
return 0;
}
vector<int> bct_path;
int curr = E;
while (curr != S) {
bct_path.push_back(curr);
curr = bct_parent[curr];
}
bct_path.push_back(S);
reverse(bct_path.begin(), bct_path.end());
vector<int> bcc_seq;
vector<int> cut_seq;
for (int i = 0; i < bct_path.size(); i++) {
if (bct_path[i] > n) {
bcc_seq.push_back(bct_path[i]);
} else {
if (i > 0 && i < bct_path.size() - 1) {
cut_seq.push_back(bct_path[i]);
}
}
}
vector<int> final_path;
if (solve_chain(bcc_seq, cut_seq, final_path)) {
fout << final_path.size() << "\n";
for (int x : final_path) fout << x << " ";
fout << "\n";
return 0;
}
reverse(bcc_seq.begin(), bcc_seq.end());
reverse(cut_seq.begin(), cut_seq.end());
if (solve_chain(bcc_seq, cut_seq, final_path)) {
fout << final_path.size() << "\n";
for (int x : final_path) fout << x << " ";
fout << "\n";
return 0;
}
fout << "No chance\n";
return 0;
}