Cod sursa(job #2971561)

Utilizator ptudortudor P ptudor Data 27 ianuarie 2023 16:50:31
Problema Santa Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 5.18 kb
#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
ifstream in("in.in");
ofstream out("out.out");
#else
#define in cin
#define out cout
#endif

const int NMAX = 45005;
int n,m,s,e,q;
typedef vector<vector<int>> Graph;
vector<vector<int>> comps;
vector<vector<pair<int,int>>> comp_graph;
Graph g;
vector<int> road;
namespace Biconex{
    int tin[NMAX],low[NMAX],viz[NMAX],timer = 0;
    void get_biconexe() {
        function<void(int,int)> dfs = [&](int node, int parent) {
            tin[node] = ++timer;
            low[node] = timer;
            for (auto k : g[node]) {
                if (k == parent) continue;
                if (tin[k] == 0) {
                    dfs(k, node);
                    low[node] = min(low[node] , low[k]);
                } else {
                    low[node] = min(low[node] , tin[k]);
                }
            }
        };

        dfs(1,0);

        function<void(int,int)> get_components = [&](int node, int id) {
            viz[node] = 1;
            for (auto k : g[node]) {
                if (viz[k] == 0) {
                    if (  low[k] >= tin[node] ) {
                        /// articulation point
                        comps.push_back({node,k});

                        comp_graph.push_back({});

                        comp_graph[(int)comps.size() - 1].push_back({id, node});
                        comp_graph[id].push_back({(int)comps.size() - 1, node});
                        
                        get_components(k , (int)comps.size() - 1);
                    } else {
                        comps[id].push_back(k);
                        get_components(k, id);
                    }
                }
            }
        };
        comp_graph.push_back({});
        comps.push_back({});

        get_components(1 , 0);
    }
}
namespace Calculate {
    const int NMAX_2 = (1 << 16);
    int id[NMAX],dp[20][NMAX_2],prev[20][NMAX_2];
    void dfs(int node, int mask) {
        for (auto k : g[node]) {
            int k_id = id[k];
            if (!(mask&(1<<k_id))) {
                int new_mask = mask^(1<<k_id);
                if (dp[id[k]][new_mask] == -1) {
                    dp[id[k]][new_mask] = 1;
                    prev[id[k]][new_mask] = node;
                    dfs(k, new_mask);
                }
            }
        }
    }
    bool found = false;
    void calculate(int comp, int start_node, int end_node) {
        if (found) {
            return;
        }
        if (end_node == e) {
            end_node = -1;
            found = true;
        }
        int sz = comps[comp].size();
        for (int i = 0; i < sz; i++) {
            id[comps[comp][i]] = i;
        }

        for (int i = 0; i < sz; i++) {
            for (int j = 0; j < (1 << sz); j++) {
                dp[i][j] = -1;
            }
        }

        dp[id[start_node]][(1 << id[start_node])] = 1;
        prev[id[start_node]][1<<id[start_node]] = 0;
        dfs(start_node, (1 << id[start_node]));
        
        int node = end_node, mask = (1<<sz) - 1;
        if (node == -1) {
            for (int i = 0; i < sz; i++) {
                if (dp[i][mask] == 1) {
                    node = comps[comp][i];
                    break;
                }
            }
        }
        stack<int> st;
        while(node != start_node) {
            st.push(node);
            int old_mask = mask;
            mask = mask ^ (1<<id[node]);
            node = prev[id[node]][old_mask];
        }

        while(!st.empty()) {
            road.push_back(st.top());
            st.pop();
        }
    }
}
int main() {
    in >> n >> m;
    g.resize(n + 1);
    for (int i = 1; i <= m; i++) {
        int u,v;
        in >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    in >> s >> e >> q;

    Biconex::get_biconexe();
/*
    for (auto k : comps) {
        for (auto y : k) {
            cout << y << " ";
        }
        cout << "\n";
    }*/

    int start_comp = 0, end_comp = 0, q_comp;
    for (int i = 0; i < comps.size(); i++) {
        for (auto y : comps[i]) {
            if (y == s) {
                start_comp = i;
            } 
            if (y == e) {
                end_comp = i;
            }
            if (y == q) {
                q_comp = i;
            }   
        }
    }

    if (q_comp != start_comp && q_comp != end_comp) {
        out << "No\n";
        return 0;
    }

    int begin_comp;
    if (q_comp == start_comp) {
        begin_comp = start_comp;
    } else {
        begin_comp = end_comp;
    }

    function<bool(int,int,int)> dfs = [&](int node, int parent, int last_node) {
        if (node == start_comp) {
            Calculate::calculate(node, q, last_node); /// go in this component from this node to another node
            return true;
        }
        for (auto k : comp_graph[node]) {
            if (k.first == parent) {
                continue;
            }
            if (dfs(k.first, node, k.second) == true) {
                Calculate::calculate(node, k.second, last_node);
                return true;
            }
        }
        return false;
    };

    dfs(end_comp , -1, -1);

    out << road.size() + 1 << "\n";
    out << q << " ";

    for (auto k : road) {
        out << k << " ";
    }
    out << "\n";
    return 0;
}