Cod sursa(job #2304281)

Utilizator rares9301Sarmasag Rares rares9301 Data 17 decembrie 2018 20:51:32
Problema Santa Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 8.88 kb

#include <fstream>

#include <vector>

#include <algorithm>

#include <map>

using namespace std;

ifstream f("santa.in");

ofstream g("santa.out");

int N, S, E, Q, M;

map <int, int> Gr;

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;

int nrc, yes = 0;

int Mark[45005];

int Artic[45005], Root,P[45005],Pos[45005], Inv[45005], St[45005], top2, a, b, c, limit, ending, bi;

int test, Power[20];

pair <int, int> Stack[200005];

int nbvis = 0;

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;

    int aux = 0;

    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)

        {

            aux++;

            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 && node != 1)

                {

                    Artic[node] = ++nr; Inv[nr] = node;

                }

 

            }

 

        }

        else

        {

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

        }

    }

    if(aux >= 2 && node == 1)

        Artic[node] = ++nr, Inv[nr] = node;

}

 

void precalcGG()

{

    Root = Artic[1] + nrc;

    for(int i = 1; i <= nrc; i++)

    {

        int father = Father[i];

        if(Artic[father] != 0)

        {

            GG[Artic[father] + nrc].push_back(i);

            GG[i].push_back(Artic[father] + nrc);

        Father[i] = Artic[father] + nrc;

        }

        else

            Father[i] = father = 0;

        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;

            if(Artic[node] != 0)

                {

                    GG[i].push_back(Artic[node] + nrc);

                    GG[Artic[node] + nrc].push_back(i);

                    Father[Artic[node] + nrc] = i;

                }

 

        }

    }

    cnt = nr + nrc;

    for(int i = 1; i <= cnt; i++)

    {

        sort(GG[i].begin(), GG[i].end());

        GG[i].erase(unique(GG[i].begin(), GG[i].end()), GG[i].end());

    }

}

int memor(int conf, int node)

{

    if(DP[conf][node] == -test)

        return 0;

    if(DP[conf][node] == test)

        return 1;

    if(conf == limit && (ending == 0 || Bic[bi][node] == ending))

    {

        DP[conf][node] = test;

        return 1;

    }

 

    for(int i = 0; i < G[Bic[bi][node]].size(); i++)

    {

        int neighb = G[Bic[bi][node]][i];

        if(Pos[neighb] != -1 && (conf & Power[Pos[neighb]]) == 0)

        {

            if(memor(conf ^ Power[Pos[neighb]], Pos[neighb]) == 1)

            {

                DP[conf][node] = test;

                Link[conf][node] = make_pair(conf ^ Power[Pos[neighb]], Pos[neighb]);

                return 1;

            }

        }

    }

    DP[conf][node] = -test;

    return 0;

}

void precalcRoad(int bic, int start, int fin)

{

    int lim = Bic[bic].size();

    ++test;

     bi = bic;

    /*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;

    //Gr.clear();

    ending = fin;

    for(int i = 0; i < Bic[bic].size(); i++)

    {

        int node = Bic[bic][i];

        if(node == start)

            ps = i;

        if(node == fin)

            pfin = i;

        Pos[node] = i;

        //Gr[node] = 1;

    }

    limit = (1 << lim) - 1;

    ok = memor((1 << ps), ps);

    /*for(int i = 0; i < Power[lim]; i++)

    {

        for(int j = 0; j < lim; j++)

        {

            if(DP[i][j] != test)

                continue;

            for(int k = 0; k < G[Bic[bic][j]].size(); k++)

            {

                int p = G[Bic[bic][j]][k];

                /*if(Gr.find(p) == Gr.end())

                    continue;

                if(Pos[p] == -1)

                    continue;

                if((i & (Power[Pos[p]])) == 0)

                {

                    DP[i ^ (Power[Pos[p]])][Pos[p]] = test;

                    Link[i ^ (Power[Pos[p]])][Pos[p]] = make_pair(i, j);

                }

            }

        }

    }*/

 

    vector <int> X;

    int mask = (1 << lim) - 1, node = -1;

    /*if(fin == 0)

    {

        for(int j = 0; j < lim; j++)

            if(DP[mask][j] == test)

            {

                node = j;

                break;

            }

    }*/

    /*else

        node = pfin;*/

    if(DP[(1 << ps)][ps] == -test)

    {

        ok = 0;

        return;

    }

    mask = (1 << ps), node = ps;

    while(mask < (1 << lim))

    {

        Solution.push_back(Bic[bic][node]);

        int m = mask, n = node;

        if(mask == (1 << lim) - 1)

            break;

        mask = Link[m][n].first; node = Link[m][n].second;

 

    }

    /*reverse(X.begin(), X.end());

    for(int i = 0; i < X.size(); i++)

        Solution.push_back(Bic[bic][X[i]]);*/

    for(int i = 0; i < Bic[bic].size(); i++)

    {

        int p = Bic[bic][i];

        Pos[p] = -1;

    }

}

 

 

void Path()

{

    int last = b;

    bool first = 0;

    for(int i = 1; i <= top2 && ok == 1; i++)

    {

        int node = St[i];

        if(node > nrc)

        {

            last = Inv[node - nrc];

            continue;

        }

        if(first == 0)

        {

            first = 1;

            ok = 0;

            for(int j = 0; j < Bic[node].size(); j++)

                if(Bic[node][j] == a)

                    ok = 1;

        }

        bool in = 0;

        for(int j = 0; j < Bic[node].size(); j++)

            if(Bic[node][j] == c)

        {

            in = 1;

            break;

        }

        if(in == 1)

            precalcRoad(node, last, 0);

        else

            precalcRoad(node, last, Inv[St[i + 1] - nrc]);

    }

 

}

void DFS2(int node, int father)

{

    St[++top2] = node;

    if(node == E)

    {

        Path();

    }

    for(int i = 0; i < GG[node].size(); i++)

    {

        int neighb = GG[node][i];

        if(neighb == father)

            continue;

        DFS2(neighb, node);

    }

 

    --top2;

}

int main()

{

    Power[0] = 1;

    for(int i = 1; i <= 17; i++)

        Power[i] = Power[i - 1] * 2;

    Read();

    for(int i = 1; i <= N; i++)

        Pos[i] = -1;

    DFS(1, 0);

    precalcGG();

    a = S; b = Q; c = E;

    if(Artic[Q] == 0)

        Q = P[Q];

    else

        Q = Artic[Q] + nrc;

    if(Artic[E] == 0)

        E = P[E];

    else

        E = Artic[E] + nrc;

    if(Artic[S] == 0)

        S = P[S];

    else

        S = Artic[S] + nrc;

    DFS2(Q, 0);

    if(ok == 0)

    {

        g << "No chance\n";

 

    }

    else

    {

        Solution.erase(unique(Solution.begin(), Solution.end()), Solution.end());

        g << Solution.size() << "\n";

        for(int i = 0; i < Solution.size(); i++)

            g << Solution[i] << " ";

        g << "\n";

    }

    return 0;

}