Cod sursa(job #2971583)

Utilizator ptudortudor P ptudor Data 27 ianuarie 2023 17:33:49
Problema Santa Scor 24
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 6.01 kb
#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
ifstream in("in.in");
ofstream out("out.out");
#else
ifstream in ("santa.in");
ofstream out ("santa.out");
#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[16][NMAX_2],prev[16][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";
    }*/

    vector<int> viz(n + 1, 0);
    vector<int> my_road;
    vector<vector<int>> components_of_node(n + 1);
    for (int i = 0; i < comps.size(); i++) {
        for (auto k : comps[i]) {
            components_of_node[k].push_back(i);
        }
    }

    vector<int> comps_apparition(comps.size());
    function<bool(int)> some_dfs = [&](int node) {
        viz[node] = 1;
        if (node == e) {
            my_road.push_back(node);
            return true;
        }
        for (auto k : g[node]) {
            if (viz[k] == 1) {
                continue;
            }
            if (some_dfs(k)) {
                my_road.push_back(node);
                return true;
            }
        }
        return false;
    };

    some_dfs(s);

    for (auto k : my_road) {
        for (auto y : components_of_node[k]) {
            comps_apparition[y]++;
        }
    }

    auto find_comp_of_node = [&](int node) {
        for (auto k : components_of_node[node]) {
            if (comps_apparition[k] > 1) {
                return k;
            }
        }
        return -1;
    };

    int start_comp = find_comp_of_node(s), end_comp = find_comp_of_node(e), q_comp = find_comp_of_node(q);

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

    if (start_comp == -1 || end_comp == -1 || q_comp == -1) {
        out << "No\n";
        return 0;
    }


    
    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;
}