Cod sursa(job #1828103)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 12 decembrie 2016 19:54:22
Problema Santa Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.29 kb
#include <fstream>
#include <vector>
#include <cstring>

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];
bool din[(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];

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[ last[ nod ] ].push_back(make_pair(nrc + 1, nod));
                gc[nrc + 1].push_back(make_pair(last[ nod ], 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) {
    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);
                if (gasit == 1) {
                    break;
                }
            }
        }
    }
    ok[ nod ] = gasit;
}

void solve (int nod, int x) {
    viz[ nod ] = 1;

    memset(din, 0, sizeof(din)); memset(r, -1, sizeof(r));
    memset(unde, -1, sizeof(unde));
    for (int i = 0; i < (int)c[ nod ].size(); ++ i) {
        unde[ c[ nod ][ i ] ] = i;
    }

    x = unde[ x ];
    din[(1 << x)][ x ] = posibil[ c[ nod ][ x ] ];

    int aux = (int)c[ nod ].size();
    vector< int > rp[(1 << lim)];

    for (int st = (1 << x) + 1; st < (1 << aux); ++ st) {
        rp[ st ].resize(aux + 1);

        if (st == (1 << aux) - 1) {
            st = st + 2 - 1;
            -- st;
        }

        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 (din[ stn ][ unde[ i ] ] == 1) {
                        din[ st ][ j ] = 1;
                        rp[ st ][ j ] = r[ st ][ j ] = unde[ i ];
                        break;
                    }
                }
            }
        }
    }

    for (int i = 0; i < aux; ++ i) {
        posibil[ c[ nod ][ i ] ] = din[(1 << aux) - 1][ i ];
    }

    aux = 0;
    for (auto i : gc[ nod ]) {
        if (viz[ i.first ] == 0 && ok[ i.first ] == 1) {
            solve(i.first, i.second);
            aux = unde[ i.second ];
        }
    }

    int stk = (1 << (int)c[ nod ].size()) - 1;
    while (aux != x) {
        int y = rp[ 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;
        care_sunt_ok(p[ S ], p[ E ], aux);

        memset(viz, 0, sizeof(viz));
        posibil[ Q ] = 1;
        solve(ind, Q);

        if (ind == p[ S ]) ind = p[ E ];
        else ind = p[ S ];

        int fin_pos = -1;
        aux = (int)c[ ind ].size();
        for (int i = 0; i < aux; ++ i) {
            if (din[(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) {
                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;
}