Cod sursa(job #1829940)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 15 decembrie 2016 21:04:17
Problema Santa Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.48 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 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< 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));
    }
}

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));
        int nod = ord[ shp ].first, x = ord[ shp ].second;

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

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

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

        for (int st = (1 << x) + 1; st < (1 << aux); ++ st) {
            if ((st & (1 << x)) == 0) continue;
            for (int j = 0; j < aux; ++ j) {
                if ((st & (1 << j)) == 0) continue;

                int stn = st - (1 << j);
                for (auto i : g[ c[ nod ][ j ] ]) {
                    if (unde[ i ] != -1 && (stn & (1 << unde[ i ]))) {
                        if (r[ stn ][ unde[ i ] ] != -1) {
                            r[ st ][ j ] = unde[ i ];
                            break;
                        }
                    }
                }
            }
        }

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