Cod sursa(job #1666785)

Utilizator atatomirTatomir Alex atatomir Data 28 martie 2016 13:12:27
Problema Santa Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.44 kb
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stack>
#include <unordered_map>
#include <queue>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 90111
#define maxNodes 16

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long
#define Point pair<int, int>

#define maxN 2016

class Buffer {
    public:
        Buffer(string name, int _dim) {
            freopen(name.c_str(), "r", stdin);
            dim = _dim;
            data.resize(dim + 5);
            refill();
        }

        Buffer& operator>>(int &dest) {
            while (!is_digit(data[pos]))
                if (++pos == dim)
                    refill();
            dest = 0;
            while (is_digit(data[pos])) {
                dest = dest * 10 + data[pos] - '0';
                if (++pos == dim)
                    refill();
            }
            return *this;
        }


    private:
        int dim, pos;
        vector<char> data;

        bool is_digit(char c) {
            return '0' <= c && c <= '9';
        }

        void refill() {
            pos = 0;
            memset(&data[0], 0, dim);
            fread(&data[0], 1, dim, stdin);
        }
};

Buffer fin("santa.in", 1 << 22);




int n, m, i, x, y;
int S, D, Q;

//! for biconnected comp
vector<int> list[maxN];
int lvl[maxN];
int low[maxN];
stack< pair<int, int> > St;

//! for tree
int cnt;
vector<int> adj[maxN];
int last[maxN];
vector<int> nodes[maxN];

//! for way
bool all_good;
bool need_swap = false;
bool us[maxN];
vector<int> way;
bool found = false;

//! for hamilton
bool in_process[maxN];
unordered_map<int, int> bit;
int prov[maxNodes][1 << maxNodes];
queue< pair<int, int> > Qu;

//! for solution
vector<int> solution;




void dfs_low(int node) {
    low[node] = lvl[node];

    for (int to : list[node]) {
        if (lvl[to]) {
            //! return edge
            low[node] = min(low[node], lvl[to]);
            continue;
        }

        //! tree edge
        St.push(mp(node, to));
        lvl[to] = lvl[node] + 1;
        dfs_low(to);
        low[node] = min(low[node], low[to]);

        if (low[to] >= lvl[node]) {
            //! new component
            cnt++;

            while (true) {
                auto top = St.top(); St.pop();

                if (last[top.first] != cnt) {
                    adj[top.first].pb(cnt);
                    adj[cnt].pb(top.first);
                    nodes[cnt].pb(top.first);

                    last[top.first] = cnt;
                }
                if (last[top.second] != cnt) {
                    adj[top.second].pb(cnt);
                    adj[cnt].pb(top.second);
                    nodes[cnt].pb(top.second);

                    last[top.second] = cnt;
                }

                if (top == mp(node, to)) break;
            }
        }
    }
}

void dfs_way(int node) {
    us[node] = true;
    way.pb(node);

    if (node == D) {
        found = true;
        return;
    }

    for (int to : adj[node])
        if (!us[to] && !found)
            dfs_way(to);


    if (!found) way.pop_back();
}

void add_solution(int id, int S, int D) {
    int i, j, target;
    vector<int> act = nodes[id];
    vector<int> local_way;
    bool dontknow = false;

    for (int i = 0; i < act.size(); i++) {
        bit[act[i]] = i;
        in_process[act[i]] = true;
    }

    S = bit[S];

    memset(prov, 0, sizeof(prov));
    prov[S][ 1 << S ] = S;
    Qu.push(mp(act[S], 1 << S));

    while (!Qu.empty()) {
        int node = Qu.front().first;
        int conf = Qu.front().second;
        Qu.pop();

        for (int to : list[node]) {
            if (!in_process[to]) continue;

            int act_bit = bit[to];
            int act_conf = conf | (1 << act_bit);

            if (conf == act_conf) continue;
            if (prov[act_bit][act_conf]) continue;

            prov[act_bit][act_conf] = bit[node] + 1;
            Qu.push(mp(to, act_conf));
        }
    }

    target = (1 << act.size()) - 1;

    if (D == 0) {
        //! destionation is irrelevant
        //! find a good one

        dontknow = true;
        for (int e : act)
            if (prov[ bit[e] ][ target ])
                D = e;
    }

    //! test if the solution is valid
    if (D == 0 || prov[ bit[D] ][target] == 0) {
        printf("No chance");
        cerr << "No chance\n";
        exit(0);
    }

    //! roll back on your way
    D = bit[D];
    local_way.clear();
    local_way.pb( act[D] );

    while (target ^ (1 << D)) {
        int aux = prov[D][target] - 1;
        target ^= (1 << D);
        D = aux;

        local_way.pb( act[D] );
    }

    reverse(local_way.begin(), local_way.end());
    if(!dontknow) local_way.pop_back();

    for (int e : local_way)
        solution.pb(e);


    for (int i = 0; i < act.size(); i++)
        in_process[act[i]] = false;
}



int main()
{
    //freopen("santa.in","r",stdin);
    freopen("santa.out","w",stdout);

    fin >> n >> m;
    for (i = 1; i <= m; i++) {
        fin >> x >> y;
        list[x].pb(y);
        list[y].pb(x);
    }
    fin >> S >> D >> Q;

    //! compute edges between components and nodes
    lvl[1] = 1;
    cnt = n;
    dfs_low(1);

    //! check if there are any solutions
    bool all_good = false;
    for (i = n + 1; i <= cnt; i++) {
        bool is_S = false;
        bool is_D = false;
        bool is_Q = false;

        for (int e : nodes[i]) {
            is_S |= (e == S);
            is_D |= (e == D);
            is_Q |= (e == Q);
        }

        all_good |= is_Q && is_S;
        all_good |= is_Q && is_D;

        if (is_Q && is_D) need_swap = true;
        if (is_Q && is_D && is_S) need_swap = (D == Q);
        if (all_good) break;
    }

    if (!all_good) {
        printf("No chance");
        cerr << "No chance\n";
        return 0;
    }

    if (need_swap) swap(S, D);

    //! now get the way through biconnected components
    n = cnt;
    dfs_way(Q);

    //! solve each component (solve the last one at the final)
    for (i = 1; i + 2 < way.size(); i += 2)
        add_solution(way[i], way[i - 1], way[i + 1]);
    //! the last one is special ... you don't know the destination
    add_solution(way[ way.size() - 2 ], way[ way.size() - 3 ], 0);

    //! print solution
    printf("%d\n", solution.size());
    for (int e : solution)
        printf("%d ", e);


    return 0;
}