Cod sursa(job #2109033)

Utilizator alex_HarryBabalau Alexandru alex_Harry Data 19 ianuarie 2018 01:27:16
Problema Santa Scor 0
Compilator cpp Status done
Runda Lista lui wefgef Marime 7.5 kb
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream f("santa.in");
ofstream g("santa.out");
int N, S, E, Q, M;
vector <int> G[45005], GG[45005];
bool Use[45005];
int Level[45005],Father[45005], nr, cnt;
int DP[(1 << 16) + 5][18];
pair <int, int> Link[(1 << 16) + 5][18];
vector <int> Bic[45005], Solution[2];
int nrc, yes = 0;
int Mark[45005];
int Artic[45005], Root,P[45005], Inv[45005];
pair <int, int> Stack[200005];
int top;
bool ok = 1;
int Lmin[45005];
void Read()
{
    f >> N >> M;
    for(int i = 1; i <= M; i++)
    {
        int x, y;
        f >> x >> y;
        G[x].push_back(y);
        G[y].push_back(x);
    }
    f >> S >> E >> Q;
}
void Sol(int node, int neighb)
{
    ++nrc;
    while(top > 0 && !(Stack[top].first == node && Stack[top].second == neighb))
    {
        Bic[nrc].push_back(Stack[top].first);
        Bic[nrc].push_back(Stack[top].second);
        --top;
    }
    Bic[nrc].push_back(node);
    Bic[nrc].push_back(neighb);
    --top;
    Father[nrc] = node;
    sort(Bic[nrc].begin(), Bic[nrc].end());
    Bic[nrc].erase(unique(Bic[nrc].begin(), Bic[nrc].end()), Bic[nrc].end());
    int aux = 0;
    for(int i = 0; i < Bic[nrc].size(); i++)
    {
        int node = Bic[nrc][i];
        if(node == Q)
            aux++;
        if(node == S)
            aux++;
    }
    if(aux == 2)
        yes = 1;
}
void DFS(int node, int father)
{
    Use[node] = 1;
    Level[node] = Level[father] + 1;
    Lmin[node] = Level[node];

    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father)
            continue;
        if(Use[neighb] == 0)
        {
            Stack[++top] = make_pair(node, neighb);
            DFS(neighb, node);
            Lmin[node] = min(Lmin[neighb], Lmin[node]);
            if(Lmin[neighb] >= Level[node])
            {
                Sol(node, neighb);
                if(Artic[node] == 0)
                {
                    Artic[node] = ++nr; Inv[nr] = node;
                }

            }

        }
        else
        {
            Lmin[node] = min(Lmin[node], Level[neighb]);
        }
    }
}

void precalcGG()
{
    Root = Artic[1] + nrc;
    for(int i = 1; i <= nrc; i++)
    {
        int father = Father[i];
        GG[Artic[father] + nrc].push_back(i);
        Father[i] = Artic[father] + nrc;
        for(int j = 0; j < Bic[i].size(); j++)
        {
            int node = Bic[i][j];
            if(node == father)
                continue;
            if(Artic[node] == 0)
                P[node] = i;
            for(int k = 0; k < G[node].size(); k++)
            {
                int neighb = G[node][k];
                if(neighb == father)
                    continue;
                if(Artic[neighb] != 0)
                {
                    GG[i].push_back(Artic[neighb] + nrc);
                    Father[Artic[neighb] + nrc] = i;
                }
            }
        }
    }
    cnt = nr + nrc;
}

void precalcRoad(int bic, int start, int fin, int ind)
{
    int lim = Bic[bic].size();
    for(int i = 0; i < (1 << lim); i++)
        for(int j = 0; j < lim; j++)
            DP[i][j] = 0, Link[i][j] = make_pair(0, 0);
    int ps = 0, pfin = 0;
    for(int i = 0; i < Bic[bic].size(); i++)
    {
        int node = Bic[bic][i];
        if(node == start)
            ps = i;
        if(node == fin)
            pfin = i;
    }
    DP[(1 << ps)][ps] = 1;
    for(int i = 0; i < (1 << lim); i++)
    {
        for(int j = 0; j < lim; j++)
        {
            if(DP[i][j] == 0)
                continue;
            for(int k = 0; k < lim; k++)
            {
                if((i & (1 << k)) == 0)
                {
                    DP[i ^ (1 << k)][k] = 1;
                    Link[i ^ (1 << k)][k] = make_pair(i, j);
                }
            }
        }
    }
    vector <int> X;
    int mask = (1 << lim) - 1, node = pfin;
    if(DP[mask][node] == 0)
    {
        ok = 0;
        return;
    }
    while(mask > 0)
    {
        X.push_back(node);
        int m = mask, n = node;
        mask = Link[m][n].first; node = Link[m][n].second;
    }
    reverse(X.begin(), X.end());
    for(int i = 0; i < X.size(); i++)
        Solution[ind].push_back(Bic[bic][X[i]]);
}

void markNodes()
{
    int node = S;
    if(Artic[S] == 0)
        node = P[node];
    else
        node = nrc + Artic[S];
    while(node != 0)
    {
        Mark[node]++;
        node = Father[node];
    }
    node = E;
    if(Artic[E] == 0)
        node = P[node];
    else
        node = nrc + Artic[E];
    while(node != 0)
    {
        Mark[node]++;
        node = Father[node];
    }
}

void Solve()
{
    int q = Q, e = E;
    if(S == Q && S == E)
    {
        g << "1\n" << S << "\n";
        return;
    }
    if(S != Q)
    {
        if(Artic[S] > 0)
    {
        S = nrc + Artic[S];
    }
    else
        S = P[S];
    if(Artic[Q] > 0)
    {
        Q = nrc + Artic[Q];
    }
    else
        Q = P[Q];
    }
    else
    {
        if(Artic[S] > 0)
            S = Q = nrc + Artic[S];
        else
            S = Q = P[S];
    }
    if(Artic[E] > 0)
    {
        E = nrc + Artic[E];
    }
    else
        E = P[E];
    int node = S, last = q, lca = -1;
    if(node > nrc)
    {
        for(int j = 0;j < GG[node].size(); j++)
        {
            int neighb = GG[node][j];
            if(Mark[neighb] >= 1)
            {
                node = neighb;
                break;
            }
        }
    }
    while(Mark[node] >= 1)
    {
        if(node > nrc)
            last = Inv[node - nrc];
        else
        {
            if(P[e] == node)
                precalcRoad(node, last, e, 0);
            else
            {
                if(Mark[node] == 1)
                    precalcRoad(node, last, Inv[Father[node] - nrc], 0);
                else
                {
                    for(int j = 0; j < GG[node].size(); j++)
                    {
                        int neighb = GG[node][j];
                        if(Mark[neighb] == 2 && Inv[neighb - nrc] != last)
                        {
                            precalcRoad(node, last, Inv[neighb], 0);
                            break;
                        }
                    }
                }
            }

        }
        lca = node;
        node = Father[node];
    }
    node = E; last = e;
    while(Mark[node] >= 1)
    {
        if(node > nrc)
            last = Inv[node - nrc];
        else
        {
            if(lca == node)
                continue;
            else
            {
                if(Mark[Father[node]] >= 1)
                    precalcRoad(node, last, Inv[Father[node] - nrc], 1);
            }

        }
        node = Father[node];
    }
    if(ok == 0)
        return;
    vector <int> Aux;
    reverse(Solution[1].begin(), Solution[1].end());
    for(int i = 0; i < Solution[0].size(); i++)
        Aux.push_back(Solution[0][i]);
    for(int i = 0; i < Solution[1].size(); i++)
        Aux.push_back(Solution[1][i]);
    g << Aux.size() << "\n";
    for(int i = 0; i < Aux.size(); i++)
        g << Aux[i] << " " ;
    g << "\n";
}
int main()
{
    Read();
    DFS(1, 0);
    precalcGG();
    markNodes();
    if(yes == 0)
        ok = 0;
    if(ok == 1)
        Solve();
    if(ok == 0)
    {
        g << "No chance\n";

    }
    return 0;
}