Cod sursa(job #1113294)

Utilizator poptibiPop Tiberiu poptibi Data 20 februarie 2014 15:36:51
Problema Santa Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.65 kb
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#include <tr1/unordered_map>
using namespace std;
using namespace tr1;

const int NMAX = 45010, MMAX = 130010, INF = 0x3f3f3f3f;

int N, M, X, Y, S, E, Q, BC[NMAX], NrBC, Low[NMAX], Level[NMAX], SizeBC[NMAX];
stack<pair<int, int> > St;
vector<pair<int, int> > G[NMAX];
vector<int> BCG[NMAX], CurrentBC;
bool Used[NMAX], Critical[MMAX], Visited;
tr1 :: unordered_map<int, int> NrE[NMAX], Start[NMAX], End[NMAX];
int Dist[NMAX], From[NMAX];
vector<int> Path, Ans, PathBC;

void GetComp(int X, int Y, int IndexClosingEdge)
{
    CurrentBC.clear();
    pair<int, int> Now;
    do
    {
        Now = St.top();
        St.pop();
        CurrentBC.push_back(Now.second);
    }while(Now.first != X && Now.second != Y);
    CurrentBC.push_back(Now.first);

    if(CurrentBC.size() == 2 && NrE[ CurrentBC[0] ][ CurrentBC[1] ] == 1)
        Critical[IndexClosingEdge] = 1;
}

void DFS_BC(int Node, int Father)
{
    Low[Node] = Level[Node];
    for(vector<pair<int, int> > :: iterator it = G[Node].begin(); it != G[Node].end(); ++ it)
    {
        if(it -> first == Father) continue;
        if(!Level[it -> first])
        {
            Level[it -> first] = Level[Node] + 1;
            St.push(make_pair(Node, it -> first));
            DFS_BC(it -> first, Node);
            Low[Node] = min(Low[Node], Low[it -> first]);
            if(Level[Node] <= Low[it -> first]) GetComp(Node, it -> first, it -> second);
        }else Low[Node] = min(Low[Node], Low[it -> first]);
    }
}

void DFS_Connected(int Node)
{
    Used[Node] = 1;
    BC[Node] = NrBC;
    SizeBC[NrBC] ++;
    for(vector<pair<int, int> > :: iterator it = G[Node].begin(); it != G[Node].end(); ++ it)
        if(!Used[it -> first] && !Critical[it -> second])
            DFS_Connected(it -> first);
}

void Build_BC_Graph()
{
    for(int i = 1; i <= N; ++ i)
    {
        for(int j = 0; j < G[i].size(); ++ j)
        {
            int Vec = G[i][j].first;
            if(BC[i] != BC[Vec])
            {
              //  printf("%i %i\n", BC[i], BC[Vec]);
                BCG[ BC[i] ].push_back(BC[Vec]);
                BCG[ BC[Vec] ].push_back(BC[i]);
                Start[ BC[i] ][ BC[Vec] ] = i;
                End[ BC[i] ][ BC[Vec] ] = Vec;
                Start[ BC[Vec] ][ BC[i] ] = Vec;
                End[ BC[Vec] ][ BC[i] ] = i;
            }
        }
    }
}

void BFS(int StartNode, int EndNode)
{
    for(int i = 1; i <= NrBC; ++ i) Dist[i] = INF;
    queue<int> Q;
    Q.push(StartNode);
    Dist[StartNode] = 1;
    while(!Q.empty())
    {
        int Node = Q.front();
        Q.pop();

        if(Node == EndNode) break;

        for(vector<int> :: iterator it = BCG[Node].begin(); it != BCG[Node].end(); ++ it)
            if(Dist[*it] == INF)
            {
                Dist[*it] = Dist[Node] + 1;
                From[*it] = Node;
                Q.push(*it);
            }
    }

    if(Dist[EndNode] == INF)
    {
        printf("No chance\n");
        exit(0);
    }

    while(Dist[EndNode] > 0)
        Path.push_back(EndNode), EndNode = From[EndNode];

    reverse(Path.begin(), Path.end());
}

void Back(int Pos, int Node, int End, int EndingBC, int NowBC)
{
    if(Visited) return ;
    if(Pos == SizeBC[ NowBC ])
    {
        if(!EndingBC && PathBC.back() != End) return ;
        Visited = 1;
        for(vector<int> :: iterator it = PathBC.begin(); it != PathBC.end(); ++ it)
            Ans.push_back(*it);
        return ;
    }

    for(vector<pair<int, int> > :: iterator it = G[Node].begin(); it != G[Node].end(); ++ it)
        if(!Used[it -> first] && BC[Node] == BC[it -> first])
        {
            if(!EndingBC && Pos < SizeBC[NowBC] - 1 && it -> first == End) continue;

            Used[it -> first] = 1;
            PathBC.push_back(it -> first);

            Back(Pos + 1, it -> first, End, EndingBC, NowBC);

            PathBC.pop_back();
            Used[it -> first] = 0;
        }
}

int main()
{
    freopen("santa.in", "r", stdin);
    freopen("santa.out", "w", stdout);

    scanf("%i %i", &N, &M);
    for(int i = 1; i <= M; ++ i)
    {
        scanf("%i %i", &X, &Y);
        G[X].push_back(make_pair(Y, i));
        G[Y].push_back(make_pair(X, i));
        NrE[X][Y] ++;
        NrE[Y][X] ++;
    }
    scanf("%i %i %i", &S, &E, &Q);

    for(int i = 1; i <= N; ++ i)
        if(!Level[i])
        {
            Level[i] = 1;
            DFS_BC(i, 0);
        }

    for(int i = 1; i <= N; ++ i)
        if(!Used[i])
        {
            ++ NrBC;
            DFS_Connected(i);
        }

    if(BC[S] != BC[Q] && BC[Q] != BC[E])
    {
        printf("No chance\n");
        return 0;
    }
    Build_BC_Graph();

    if(BC[S] == BC[Q]) BFS(BC[Q], BC[E]);
    else BFS(BC[Q], BC[S]);

    memset(Used, 0, sizeof(Used));

    for(int i = 0; i < Path.size(); ++ i)
    {
        int StartNode, EndNode, EndingBC;
        if(i == 0) StartNode = Q;
        else StartNode = Start[ Path[i] ][ Path[i - 1] ];
        if(i == Path.size() - 1) EndNode = -1, EndingBC = 1;
        else EndingBC = 0, EndNode = Start[ Path[i] ][ Path[i + 1] ];

        Visited = 0;
        PathBC.clear();
        Used[StartNode] = 1;
        PathBC.push_back(StartNode);
        Back(1, StartNode, EndNode, EndingBC, Path[i]);

        if(!Visited)
        {
            printf("No chance\n");
            return 0;
        }
    }

    printf("%i\n", Ans.size());
    for(int i = 0; i < Ans.size(); ++ i)
        printf("%i ", Ans[i]);
}