Cod sursa(job #732818)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 11 aprilie 2012 00:28:19
Problema Santa Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.32 kb
#include <cstdio>
#include <vector>
#include <stack>
#include <algorithm>
#include <cstring>

#define NMax 50000
#define TMax 100000
#define x first
#define y second
#define DMax 16

using namespace std;

vector <int> G[NMax], T[TMax], CG[DMax];
vector < vector <int> > BC;
int N, S, E, Q;
int Level[NMax], MinLevel[NMax];
stack < pair <int, int> > Edges;
bool CNode[NMax], EndC[NMax], Possible;
int CIndex[TMax], Index[NMax], F[1<<DMax][DMax];
vector <int> Path, Solution;

inline void BuildC (int C)
{
    for (int i=0; i<(int)BC[C].size (); ++i)
    {
        Index[BC[C][i]]=i;
    }
    for (int i=0; i<(int)BC[C].size (); ++i)
    {
        int X=BC[C][i];
        for (vector <int> :: iterator Y=G[X].begin (); Y!=G[X].end (); ++Y)
        {
            if (Index[*Y]!=-1)
            {
                CG[Index[X]].push_back (Index[*Y]);
            }
        }
    }
    for (int Conf=0; Conf<(1<<BC[C].size ()); ++Conf)
    {
        for (int X=0; X<(int)BC[C].size (); ++X)
        {
            F[Conf][X]=-1;
        }
    }
}

inline void EraseC (int C)
{
    for (int i=0; i<(int)BC[C].size (); ++i)
    {
        CG[i].clear ();
    }
    for (int i=0; i<(int)BC[C].size (); ++i)
    {
        Index[BC[C][i]]=-1;
    }
}

int Stack[DMax]; bool Used[DMax];

inline bool Back (int K, int C, int Finish, vector <int> &CPath)
{
    if (K-1==(int)BC[C].size ())
    {
        if (Finish>N or Stack[K-1]==Finish)
        {
            Used[Stack[1]]=false;
            for (int i=2; i<K; ++i)
            {
                Used[Stack[i]]=false;
                CPath.push_back (BC[C][Stack[i]]);
            }
            return true;
        }
        return false;
    }
    int X=Stack[K-1];
    for (vector <int> :: iterator Y=CG[X].begin (); Y!=CG[X].end (); ++Y)
    {
        if (Used[*Y]) continue;
        Used[*Y]=true; Stack[K]=*Y;
        if (Back (K+1, C, Finish, CPath)) return true;
        Used[*Y]=false; Stack[K]=0;
    }
}

inline vector <int> SolveC (int C, int Start, int Finish)
{
    vector <int> CPath;
    BuildC (C);
    Start=Index[Start];
    if (Finish<=N) Finish=Index[Finish];
    Stack[1]=Start; Used[Start]=true;
    Back (2, C, Finish, CPath);
    EraseC (C);
    return CPath;
}

inline bool PathDFS (int X, int Father)
{
    Path.push_back (X);
    if ((X==E) or (X>N and EndC[X-N-1])) return true;
    for (vector <int> :: iterator Y=T[X].begin (); Y!=T[X].end (); ++Y)
    {
        if (*Y==Father) continue;
        if (PathDFS (*Y, X)) return true;
    }
    Path.pop_back ();
    return false;
}

bool ValidG ()
{
    bool Valid=false;
    for (int i=0; i<(int)BC.size (); ++i)
    {
        bool VQ=false, VS=false, VE=false;
        for (int j=0; j<(int)BC[i].size (); ++j)
        {
            VQ|=(BC[i][j]==Q);
            VS|=(BC[i][j]==S);
            VE|=(BC[i][j]==E);
        }
        if (VQ and (VS or VE)) Valid=true;
        EndC[i]=VE;
    }
    return Valid;
}

bool BuildPath ()
{
    if (!ValidG ()) return false;
    int Start, Finish;
    if (CIndex[Q]==-1) Start=Q;
    else
    {
        Start=CIndex[Q]+N+1; Path.push_back (Q);
    }
    if (!PathDFS (Start, Start)) return false;
    Solution.push_back (Q);
    for (int i=0; i<(int)Path.size (); ++i)
    {
        if (Path[i]<=N) continue;
        Start=Path[i-1];
        if (i+1<(int)Path.size ()) Finish=Path[i+1];
        else Finish=N+1;
        vector <int> CPath=SolveC (Path[i]-N-1, Start, Finish);
        if (CPath.empty ()) return false;
        for (int j=0; j<(int)CPath.size (); ++j)
        {
            Solution.push_back (CPath[j]);
        }
    }
    return true;
}

inline void DetBC (int X, int Y)
{
    vector <int> Component;
    int NewX, NewY;
    do
    {
        NewX=Edges.top ().x, NewY=Edges.top ().y;
        Edges.pop ();
        Component.push_back (NewX); Component.push_back (NewY);
    }
    while (NewX!=X or NewY!=Y);
    sort (Component.begin (), Component.end ());
    Component.erase (unique (Component.begin (), Component.end ()), Component.end ());
    for (int i=0; i<(int)Component.size (); ++i)
    {
        CIndex[Component[i]]=BC.size ();
    }
    BC.push_back (Component);
}

inline void ComponentDFS (int X, int Father, int L)
{
    Level[X]=MinLevel[X]=L;
    int NSons=0; bool Critical=false;
    for (vector <int> :: iterator Y=G[X].begin (); Y!=G[X].end (); ++Y)
    {
        if (*Y==Father) continue;
        if (!Level[*Y])
        {
            ++NSons; Edges.push (make_pair (X, *Y));
            ComponentDFS (*Y, X, L+1);
            if (MinLevel[*Y]>=Level[X])
            {
                Critical=true; DetBC (X, *Y);
            }
        }
    }
    for (vector <int> :: iterator Y=G[X].begin (); Y!=G[X].end (); ++Y)
    {
        if (*Y==Father) continue;
        MinLevel[X]=min (MinLevel[X], MinLevel[*Y]);
    }
    if (X==Father)
    {
        if (NSons>1) CNode[X]=true;
    }
    else
    {
        if (Critical) CNode[X]=true;
    }
}

void BuildComponents ()
{
    for (int i=1; i<=N; ++i)
    {
        if (!Level[i]) ComponentDFS (i, i, 1);
    }
    for (int i=1; i<=N; ++i)
    {
        if (CNode[i]) CIndex[i]=-1;
    }
}

void BuildTree ()
{
    for (int i=0; i<(int)BC.size (); ++i)
    {
        for (int j=0; j<(int)BC[i].size (); ++j)
        {
            if (CNode[BC[i][j]])
            {
                T[BC[i][j]].push_back (N+i+1);
                T[N+i+1].push_back (BC[i][j]);
            }
        }
    }
}

void Solve ()
{
    BuildComponents ();
    BuildTree ();
    memset (Index, -1, sizeof (Index));
    Possible=BuildPath ();
}

void Read ()
{
    freopen ("santa.in", "r", stdin);
    int M; scanf ("%d %d", &N, &M);
    for (; M>0; --M)
    {
        int X, Y; scanf ("%d %d", &X, &Y);
        G[X].push_back (Y); G[Y].push_back (X);
    }
    scanf ("%d %d %d", &S, &E, &Q);
}

void Print ()
{
    freopen ("santa.out", "w", stdout);
    if (!Possible) printf ("No chance\n");
    else
    {
        printf ("%d\n", (int)Solution.size ());
        for (int i=0; i<(int)Solution.size (); ++i)
        {
            printf ("%d ", Solution[i]);
        }
        printf ("\n");
    }
}

int main()
{
    Read ();
    Solve ();
    Print ();
    return 0;
}