Cod sursa(job #3263190)

Utilizator not_anduAndu Scheusan not_andu Data 13 decembrie 2024 19:45:52
Problema Santa Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.4 kb
/*

ruta cadouri: S --> E
elfii nu trec de doua ori prin aceasi intersectie
pleaca din Q spre toate intersectiile unde transportul ar putea ajunge
! comp binconexa <= 15 noduri - generare backtracking posibile + hamilton

*/

#include <bits/stdc++.h>

using namespace std;

#define INFILE "santa.in"
#define OUTFILE "santa.out"

const int N_MAX = 45000;

int nodes, edges;
int S, E, Q;

vector<int> adj[N_MAX + 5];

bool onPath[N_MAX + 5];
bool visited[N_MAX + 5];
vector<int> path;

int d[N_MAX + 5];
int level[N_MAX + 5];
stack<int> st;

vector<int> articulatii;
vector<vector<int> > compBiconexe;

void finishedProgram(){
    cout << "No chance" << '\n';
    exit(0);
}

void getComponent(int node, int son){
    if(!onPath[son]){
        while(st.top() != son) st.pop();
        st.pop();
        return;
    }

    compBiconexe.push_back(vector<int>());
    articulatii.push_back(node);

    while(st.top() != son){
        compBiconexe.back().push_back(st.top());
        st.pop();
    }
    st.pop();

    compBiconexe.back().push_back(son);
    compBiconexe.back().push_back(node);

}

void dfs(int node, int parent){

    visited[node] = true;
    level[node] = level[parent] + 1;
    d[node] = level[node];

    for(auto &to : adj[node]){
        if(to == parent) continue;
        
        if(visited[to]) d[node] = min(d[node], level[to]);
        else {

            st.push(to);
            dfs(to, node);

            onPath[node] |= onPath[to];
            d[node] = min(d[node], d[to]);

            if(d[to] >= level[node]) getComponent(node, to);

        }

    }

}

bool backtracking(int cnt, int size, int node, int end) {

    visited[node] = true;
    if(cnt > 1) path.push_back(node);

    if(cnt == size) {
        if(end == 0 || node == end) return true;
        visited[node] = false;
        path.pop_back();
        return false;
    }

    for(auto &to : adj[node]){
        if(!visited[to] && (to != end || cnt == size - 1) && backtracking(cnt + 1, size, to, end)) return true;
    }

    visited[node] = false;
    path.pop_back();
    return false;

}

void solveBiconex(vector<int> &nodes, int start, int end){

    for(auto &it : nodes){
        visited[it] = false;
    }

    if(!backtracking(1, nodes.size(), start, end)) finishedProgram();

}

void solve(){

    cin >> nodes >> edges;
    for(int i = 0; i < edges; ++i){
        int node1, node2; cin >> node1 >> node2;
        adj[node1].push_back(node2);
        adj[node2].push_back(node1);
    }

    cin >> S >> E >> Q;

    onPath[S] = true;
    articulatii.assign(1, S);
    compBiconexe.resize(1);

    dfs(E, 0);
    if(!onPath[E]) finishedProgram();

    if(find(compBiconexe[1].begin(), compBiconexe[1].end(), Q) == compBiconexe[1].end()){
        reverse(compBiconexe.begin() + 1, compBiconexe.end());
        reverse(articulatii.begin(), articulatii.end());
    }

    if(find(compBiconexe[1].begin(), compBiconexe[1].end(), Q) == compBiconexe[1].end()){
        finishedProgram();
    }

    articulatii[0] = Q;
    articulatii.back() = 0;

    path.push_back(Q);

    for(int i = 1; i < compBiconexe.size(); ++i){
        solveBiconex(compBiconexe[i], articulatii[i - 1], articulatii[i]);
    }

    cout << path.size() << '\n';
    for(auto &it : path) cout << it << " ";
    cout << '\n';

}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    freopen(INFILE, "r", stdin);
    freopen(OUTFILE, "w", stdout);
    solve();
    return 0;
}