Cod sursa(job #731888)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 9 aprilie 2012 13:20:12
Problema Santa Scor 30
Compilator cpp Status done
Runda Lista lui wefgef Marime 7.13 kb
#include <cstdio>
#include <vector>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cassert>

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

inline vector <int> SolveC (int C, int Start, int Finish)
{
    BuildC (C);
    F[1<<Index[Start]][Index[Start]]=Index[Start];
    for (int Conf=1; Conf<(1<<BC[C].size ()); ++Conf)
    {
        for (int X=0; X<(int)BC[C].size (); ++X)
        {
            if (!(Conf&(1<<X))) continue;
            for (vector <int> :: iterator Y=CG[X].begin (); Y!=CG[X].end (); ++Y)
            {
                if (!(Conf&(1<<(*Y)))) continue;
                int PConf=Conf^(1<<X);
                if (F[PConf][*Y]!=-1)
                {
                    F[Conf][X]=*Y; break;
                }
            }
        }
    }
    vector <int> CPath;
    int Conf=(1<<BC[C].size ())-1, X=Index[Finish];
    if (F[Conf][X]==-1) return CPath;
    while (X!=Index[Start])
    {
        CPath.push_back (BC[C][X]);
        int PConf=Conf^(1<<X);
        X=F[Conf][X]; Conf=PConf;
    }
    reverse (CPath.begin (), CPath.end ());
    EraseC (C);
    return CPath;
}

inline bool PathDFS (int X, int Father, int L)
{
    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, L+1)) 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 ()
{
    assert (BC.size ()+N+1<=150000);
    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, 0)) 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];
            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]);
            }
        }
        else
        {
            vector <int> CPath;
            for (int j=0; j<(int)BC[Path[i]-N-1].size (); ++j)
            {
                Finish=BC[Path[i]-N-1][j];
                CPath=SolveC (Path[i]-N-1, Start, Finish);
                if (CPath.empty ()) continue;
                for (int k=0; k<(int)CPath.size (); ++k)
                {
                    Solution.push_back (CPath[k]);
                }
                break;
            }
            if (CPath.empty ()) return false;
        }
    }
    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]);
            }
        }
    }
    for (int X=1; X<=N; ++X)
    {
        if (!CNode[X]) continue;
        for (vector <int> :: iterator Y=G[X].begin (); Y!=G[X].end (); ++Y)
        {
            if (CNode[*Y]) T[X].push_back (*Y);

        }
    }
}

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