Cod sursa(job #2212632)

Utilizator NOSCOPEPROKENDYMACHEAMACUMVREAU NOSCOPEPROKENDY Data 14 iunie 2018 15:46:32
Problema Santa Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 8.22 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;
}