Cod sursa(job #1844721)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 10 ianuarie 2017 13:01:56
Problema Santa Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.94 kb
#include <fstream>
#include <vector>
#include <cstring>
#include <algorithm>

using namespace std;

ifstream fin ("santa.in"); ofstream fout ("santa.out");

typedef vector< int > graf;

const int nmax = 45e3 + 5;
const int mmax = 13e4 + 5;
const int lim = 15;
const int inf = 1 << 30;

int n, S, E, Q;
bool viz[nmax + 1], posibil[nmax + 1], ok[mmax + 1];
int h[nmax + 1], d[nmax + 1], last[nmax + 1], p[nmax + 1], unde[nmax + 1];

int _nod;
int r[(1 << lim)][lim + 1];
int t[nmax + 1];

graf g[nmax + 1];

int nrc;
vector< int > c[mmax + 1];
vector< pair<int, int> > gc[mmax + 1];
vector< int > gaux[lim + 1];

vector< pair<int, int> > ord;

void dfs (int nod) {
    d[ nod ] = inf;
    viz[ nod ] = 1;
    for (auto i : g[ nod ]) {
        if (viz[ i ] == 0) {
            h[ i ] = h[ nod ] + 1;
            dfs( i );

            d[ nod ] = min(d[ nod ], d[ i ]);
        } else {
            d[ nod ] = min(d[ nod ], h[ i ]);
        }
    }
}

void calc_comp (int nod, int x) {
    if (p[ nod ] == 0) p[ nod ] = x;

    c[ x ].push_back( nod ); last[ nod ] = x;
    viz[ nod ] = 1;

    for (auto i : g[ nod ]) {
        if (viz[ i ] == 0) {
            if (d[ i ] >= h[ nod ]) {
                gc[ x ].push_back(make_pair(nrc + 1, nod));
                gc[nrc + 1].push_back(make_pair(x, nod));

                ++ nrc;
                c[ nrc ].push_back( nod ); last[ nod ] = nrc;

                calc_comp(i, nrc);
            } else {
                calc_comp(i, x);
            }
        }
    }
}

void care_sunt_ok (int nod, int dest, int &gasit, int k) {
    viz[ nod ] = 1;
    if (nod == dest) {
        gasit = 1;
    } else {
        for (auto i : gc[ nod ]) {
            if (viz[ i.first ] == 0) {
                care_sunt_ok(i.first, dest, gasit, i.second);
                if (gasit == 1) {
                    break;
                }
            }
        }
    }
    ok[ nod ] = gasit;
    if (gasit == 1) {
        ord.push_back(make_pair(nod, k));
    }
}

bool bck (int st, int pos, int term) {
    if (st == (1 << c[ _nod ].size()) - 1) {
        return (c[ _nod ][ pos ] == term);
    }
    if (c[ _nod ][ pos ] == term) {
        return 0;
    }

    bool gata = 0;
    for (auto i : gaux[ pos ]) {
        if (unde[ i ] != -1 && viz[ unde[ i ] ] == 0) {
            int u = unde[ i ];
            if (r[st + (1 << u)][ u ] == -1) {
                viz[ u ] = 1;
                r[st + (1 << u)][ u ] = pos;

                gata |= bck(st + (1 << u), u, term);
                if (gata == 1) return 1;

                viz[ u ] = 0;
            }
        }

    }
    return 0;
}

void solve () {
    reverse(ord.begin(), ord.end());
    posibil[ Q ] = 1;

    for (int shp = 0; shp < (int)ord.size(); ++ shp) {
        memset(r, -1, sizeof(r));
        memset(unde, -1, sizeof(unde));
        _nod = ord[ shp ].first;
        int x = ord[ shp ].second;

        for (int i = 0; i < (int)c[ _nod ].size(); ++ i) {
            unde[ c[ _nod ][ i ] ] = i;
        }

        for (int i = 0; i < (int)c[ _nod ].size(); ++ i) {
            viz[ i ] = 0;
            gaux[ i ].clear();

            for (auto j : g[ c[ _nod ][ i ] ]) {
                if (unde[ j ] != -1) {
                    gaux[ i ].push_back( j );
                }
            }
        }

        x = unde[ x ];
        if (posibil[ c[ _nod ][ x ] ] == 0) return ;
        r[(1 << x)][ x ] = inf;

        int aux = (int)c[ _nod ].size();

        viz[ x ] = 1;
        bck((1 << x), x, (shp != (int)ord.size() - 1 ? ord[shp + 1].second : -1));

        for (int i = 0; i < aux; ++ i) {
            posibil[ c[ _nod ][ i ] ] = (r[(1 << aux) - 1][ i ] != -1);
        }

        if (shp != (int)ord.size() - 1) {
            aux = unde[ ord[shp + 1].second ];
            int stk = (1 << (int)c[ _nod ].size()) - 1;
            while (aux != x && r[ stk ][ aux ] != -1) {
                int y = r[ stk ][ aux ];
                t[ c[ _nod ][ y ] ] = c[ _nod ][ aux ];

                stk -= (1 << aux);
                aux = y;
            }
        }
    }
}

int main() {
    int m;
    fin >> n >> m;
    for (int i = 1; i <= m; ++ i) {
        int x, y;
        fin >> x >> y;
        g[ x ].push_back( y ); g[ y ].push_back( x );
    }
    fin >> S >> E >> Q;

    dfs( S );

    nrc = 1;
    memset(viz, 0, sizeof(viz));
    calc_comp(S, 1);
    if (c[ 1 ].size() == 1) {
        p[ S ] = 2;
    }

    int ind = -1;
    if (p[ S ] > 0 && p[ E ] > 0) {
        for (auto i : c[ p[ S ] ]) {
            if (i == Q) {
                ind = p[ S ]; break;
            }
        }
        for (auto i : c[ p[ E ] ]) {
            if (i == Q) {
                ind = p[ E ]; break;
            }
        }
    }

    if (ind == -1) {
        fout << "No chance\n";
    } else {
        memset(viz, 0, sizeof(viz));

        int aux = 0;
        if (c[ 1 ].size() == 1) viz[ 1 ] = 1;
        if (ind == p[ S ]) care_sunt_ok(p[ S ], p[ E ], aux, Q);
        else               care_sunt_ok(p[ E ], p[ S ], aux, Q);

        solve();

        int fin_pos = -1;
        ind = ord.back().first;
        aux = (int)c[ ind ].size();
        for (int i = 0; i < aux; ++ i) {
            if (r[(1 << aux) - 1][ i ] != -1) {
                fin_pos = i;
            }
        }

        if (fin_pos == -1) {
            fout << "No chance\n";
        } else {
            aux = (1 << aux) - 1;
            int x = fin_pos;
            while (r[ aux ][ x ] != -1 && r[ aux ][ x ] != inf) {
                int y = r[ aux ][ x ];
                t[ c[ ind ][ y ] ] = c[ ind ][ x ];

                aux -= (1 << x);
                x = y;
            }

            vector< int > ans;
            fin_pos = c[ ind ][fin_pos];
            while (Q != fin_pos) {
                ans.push_back( Q );
                Q = t[ Q ];
            }
            ans.push_back(fin_pos);

            fout << ans.size() << "\n";
            for (auto i : ans) {
                fout << i << " ";
            }
            fout << "\n";
        }
    }

    fin.close();
    fout.close();
    return 0;
}