Cod sursa(job #3358619)

Utilizator rares89_Dumitriu Rares rares89_ Data 18 iunie 2026 17:08:59
Problema Santa Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 5.74 kb
#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;
vector<pair<int, int>> st;
vector<vector<int>> bccs;

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_back({u, v});
        } else {
            st.push_back({u, v});
            dfs(v, u);
            low[u] = min(low[u], low[v]);
            if (low[v] >= dfn[u]) {
                vector<int> bcc;
                while (true) {
                    auto edge = st.back(); 
                    st.pop_back();
                    bcc.push_back(edge.first);
                    bcc.push_back(edge.second);
                    if (edge.first == u && edge.second == v) break;
                }
                sort(bcc.begin(), bcc.end());
                bcc.erase(unique(bcc.begin(), bcc.end()), bcc.end());
                bccs.push_back(bcc);
            }
        }
    }
}

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> bct[90005];
vector<int> bct_path;
bool get_path(int u, int p) {
    bct_path.push_back(u);
    if (u == E) return true;
    for (int v : bct[u]) {
        if (v != p && get_path(v, u)) return true;
    }
    bct_path.pop_back();
    return false;
}

int memo[32768][16];
int memo_timer[32768][16];
int current_timer = 0;
int next_node[32768][16];
int cur_k, target_idx;
int adj_mask[16];

bool solve_dp(int mask, int u) {
    if (mask == (1 << cur_k) - 1) {
        return (target_idx == -1 || u == target_idx);
    }
    if (memo_timer[mask][u] == current_timer) return memo[mask][u];

    memo_timer[mask][u] = current_timer;
    
    int available = adj_mask[u] & ~mask;
    while (available) {
        int v = __builtin_ctz(available);
        available &= (available - 1);
        
        if (solve_dp(mask | (1 << v), v)) {
            next_node[mask][u] = v;
            return memo[mask][u] = 1;
        }
    }
    return memo[mask][u] = 0;
}

vector<int> final_ans;
vector<int> cur_bcc_nodes;

bool try_chain(vector<int>& B, vector<int>& C) {
    bool q_found = false;
    for (int x : bccs[B[0]]) {
        if (x == Q) q_found = true;
    }
    if (!q_found) return false;

    vector<int> path;
    for (int i = 0; i < (int)B.size(); i++) {
        int start_node = (i == 0) ? Q : C[i];
        int end_node = (i == (int)B.size() - 1) ? -1 : C[i + 1];

        cur_bcc_nodes = bccs[B[i]];
        cur_k = cur_bcc_nodes.size();
        
        if (cur_k > 16) return false;

        int start_idx = -1;
        target_idx = -1;
        for (int j = 0; j < cur_k; j++) {
            if (cur_bcc_nodes[j] == start_node) start_idx = j;
            if (cur_bcc_nodes[j] == end_node) target_idx = j;
        }

        if (start_idx == -1) return false;
        if (end_node != -1 && target_idx == -1) return false;

        for (int u = 0; u < cur_k; u++) {
            adj_mask[u] = 0;
            for (int v = 0; v < cur_k; v++) {
                if (u != v && has_edge(cur_bcc_nodes[u], cur_bcc_nodes[v])) {
                    adj_mask[u] |= (1 << v);
                }
            }
        }

        current_timer++;
        if (!solve_dp(1 << start_idx, start_idx)) return false;

        vector<int> bcc_path;
        int mask = 1 << start_idx;
        int u = start_idx;
        while (mask != (1 << cur_k) - 1) {
            bcc_path.push_back(cur_bcc_nodes[u]);
            int v = next_node[mask][u];
            mask |= (1 << v);
            u = v;
        }
        bcc_path.push_back(cur_bcc_nodes[u]);

        if (i == 0) {
            path = bcc_path;
        } else {
            for (int j = 1; j < (int)bcc_path.size(); j++) {
                path.push_back(bcc_path[j]);
            }
        }
    }
    final_ans = 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());
    }

    dfs(S);

    for (int i = 0; i < (int)bccs.size(); i++) {
        for (int u : bccs[i]) {
            bct[u].push_back(n + 1 + i);
            bct[n + 1 + i].push_back(u);
        }
    }

    if (!get_path(S, 0)) {
        fout << "No chance\n";
        return 0;
    }

    vector<int> b_seq, c_seq;
    for (int i = 0; i < (int)bct_path.size(); i++) {
        if (i % 2 == 1) b_seq.push_back(bct_path[i] - n - 1);
        else c_seq.push_back(bct_path[i]);
    }

    if (b_seq.empty()) {
        if (Q == S) {
            fout << 1 << "\n" << S << "\n";
        } else {
            fout << "No chance\n";
        }
        return 0;
    }

    if (try_chain(b_seq, c_seq)) {
        fout << final_ans.size() << "\n";
        for (int i = 0; i < (int)final_ans.size(); i++) {
            fout << final_ans[i] << (i + 1 == (int)final_ans.size() ? "" : " ");
        }
        fout << "\n";
        return 0;
    }

    reverse(b_seq.begin(), b_seq.end());
    reverse(c_seq.begin(), c_seq.end());

    if (try_chain(b_seq, c_seq)) {
        fout << final_ans.size() << "\n";
        for (int i = 0; i < (int)final_ans.size(); i++) {
            fout << final_ans[i] << (i + 1 == (int)final_ans.size() ? "" : " ");
        }
        fout << "\n";
        return 0;
    }

    fout << "No chance\n";
    return 0;
}