Cod sursa(job #843162)

Utilizator stoicatheoFlirk Navok stoicatheo Data 27 decembrie 2012 15:19:32
Problema Santa Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.99 kb
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string.h>
 
using namespace std;
 
#define Nmax 45005
#define Mmax 130005
#define sz(a) (int)(a.size())
 
vector< vector<int> > vec, comp, nod, vcomp;
vector<int> aux, aux2, drum, rez;
 
int n, f1, f2, f3;
int viz[Nmax], par[Nmax], niv[Nmax], nivmax[Nmax], cont, m1[Mmax], m2[Mmax], nrc, viz2[Nmax];
char mf1[Nmax], mf2[Nmax], mf3[Nmax], nosol, ad[16][16];
int Q[Mmax], ppar[Mmax], elpar[Mmax], ord[Nmax], timp[Nmax];
int c[16][1<<16], cnt, Qi[16*(1<<16)], Qj[16*(1<<16)], Qp[16*(1<<16)];
 
void readdata()
{
    freopen("santa.in", "r", stdin);
    freopen("santa.out", "w", stdout);
     
    int i, m, a, b;
     
    scanf("%d %d", &n, &m);
    vec.resize(n+1);
    for (i = 1; i <= m; ++i)
    {
        scanf("%d %d", &a, &b);
        vec[a].push_back(b);
        vec[b].push_back(a);
    }
    scanf("%d %d %d", &f1, &f2, &f3);
}
 
//componente biconexe
void insert(int x, int y)
{
    m1[++cont] = x;
    m2[cont] = y;
}
 
void scoate(int x, int y)
{
    int i;
     
    aux.clear();
    while (m1[cont] != x || m2[cont] != y)
    {
        aux.push_back(m1[cont]);
        aux.push_back(m2[cont--]);
    }
    aux.push_back(m1[cont]);
    aux.push_back(m2[cont--]);
    sort(aux.begin(), aux.end());
     
    aux2.clear();
    aux2.push_back(aux[0]);
    for (i = 1; i < sz(aux); ++i)
        if (aux[i] > aux[i-1])
            aux2.push_back(aux[i]);
                     
    comp.push_back(aux2);
    for (i = 0; i < sz(aux2); ++i)
        nod[aux2[i]].push_back(nrc);
    nrc++;
}
 
void df(int k)
{
    int i, lim, nod;
     
    viz[k] = 1;
    nivmax[k] = niv[k];
     
    lim = sz(vec[k]);
    for (i = 0; i < lim; ++i)
    {
        nod = vec[k][i];
        if (!viz[nod])
        {
            par[nod] = k;
            niv[nod] = niv[k]+1;
            insert(k, nod);
            df(nod);
            if (nivmax[nod] < nivmax[k]) nivmax[k] = nivmax[nod];
            if (nivmax[nod] >= niv[k]) scoate(k, nod);
        }
        else
        if (nod != par[k] && niv[nod] < niv[k])
        {
            insert(k, nod);
            if (niv[nod] < nivmax[k])
                nivmax[k] = niv[nod];
        }
    }
}
//end of componente biconexe
 
 
void lee()
{
    int i, j, lim, start = -1, m1 = 0, m2 = 0, ind = 1, cur, val, nou;
     
    cont = 1;
    for (i = 0; i < nrc; ++i)
    {
        lim = sz(comp[i]);
        for (j = 0; j < lim; ++j)
        {
            if (comp[i][j] == f1) mf1[i] = 1;
            if (comp[i][j] == f2) mf2[i] = 1;
            if (comp[i][j] == f3) mf3[i] = 1;
        }
    }
    for (i = 0; i < nrc; ++i)
        if (mf1[i] && mf3[i] || mf2[i] && mf3[i])
        { start = i; break; }
    if (start == -1) { nosol = 1; return; }
     
    //lee propriu-zis
    memset(viz, 0, sizeof(viz));
    Q[1] = start;
    elpar[1] = f3;
    viz2[start] = 1;
     
    if (mf1[start]) m1 = 1;
    if (mf2[start]) m2 = 1;
 
    while (!(m1 && m2))
    {
        cur = Q[ind];
        lim = comp[cur].size();
        for (i = 0; i < lim; ++i)
        if (!viz[comp[cur][i]])
        {
            val = comp[cur][i];
            viz[val] = 1;
            for (j = 0; j < sz(nod[val]); ++j)
                if (!viz2[nod[val][j]])
                {
                    nou = nod[val][j];
                    viz2[nou] = 1;
                    Q[++cont] = nou;
                    ppar[cont] = ind;
                    elpar[cont] = val;
                    if (mf1[nou]) m1 = 1;
                    if (mf2[nou]) m2 = 1;
                    if (m1 && m2) return;
                }
        }
        ++ind;
    }
}
 
int found, e[16], nr, start1, stop1;
char eviz[16];
 
void back(int k)
{
    if (k == nr)
    { found = 1; return; }
    for (int i = 0; i < nr; ++i)
    {
        if (!eviz[i] && ad[e[k-1]][i] )
        if ((i != start1) || (k == nr-1))
        {
            e[k] = i;
            eviz[i] = 1;
            back(k+1);
            eviz[i] = 0;
        }
        if (found) return;
    }
}
 
void dinamica(int start, int stop, int ind)
{
    int i, j, nod, nod2, el[16], lim, lim2;
     
    nr = sz(comp[ind]);
     
    //matrice de adiacenta
    memset(ad, 0, sizeof(ad));  
    lim = sz(comp[ind]);
    for (i = 0; i < lim; ++i)
    {
        ord[comp[ind][i]] = i;
        el[i] = comp[ind][i];
        timp[comp[ind][i]] = ind+1;
    }
    for (i = 0; i < lim; ++i)
    {
        nod = comp[ind][i];
        lim2 = sz(vec[nod]);
        for (j = 0; j < lim2; ++j)
        {
            nod2 = vec[nod][j];
            if (timp[nod2] == ind+1)
                ad[ord[nod]][ord[nod2]] = 1;
        }
    }
     
    //back de cacat, altceva mai inteligent nu intra in timp
    stop1 = ord[stop];
    if (start > -1) start1 = ord[start]; else start1 = -1;
     
    e[0] = stop1;
    found = 0;
    memset(eviz, 0, sizeof(eviz));
    eviz[stop1] = 1;
    back(1);
 
    for (i = nr-1; i >= 0; --i)
        drum.push_back(el[e[i]]);
}
 
int main()
{
    readdata();
    nod.resize(n+1);
    df(1);
    lee();
     
    if (nosol)
    {
        printf("No chance\n");
        return 0;
    }
     
    int last, pz, i;
     
    dinamica(-1, elpar[cont], Q[cont]); 
    if (nosol)
    {
        printf("No chance\n");
        return 0;
    }
     
    pz = ppar[cont]; last = elpar[cont];
    while (pz > 0)
    {
        dinamica(last, elpar[pz], Q[pz]);
        if (nosol)
        {
            printf("No chance\n");
            return 0;
        }       
        last = elpar[pz];
        pz = ppar[pz];
    }
     
    reverse(drum.begin(), drum.end());
    rez.push_back(drum[0]);
    for (i = 1; i < drum.size(); ++i)
        if (drum[i] != drum[i-1])
            rez.push_back(drum[i]);
             
    printf("%d\n", rez.size());         
    for (i = 0; i < rez.size(); ++i)
        printf("%d ", rez[i]);
     
    return 0;
}