Cod sursa(job #843161)

Utilizator stoicatheoFlirk Navok stoicatheo Data 27 decembrie 2012 15:18:46
Problema Santa Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 7.54 kb
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
 
using namespace std;
 
#define MAXN 45005
 
int N, M;
int S, D, Qs;
vector<int> con[MAXN];
int alt[MAXN], p[MAXN], low[MAXN], art[MAXN], u[MAXN];
 
vector<int> nodincomp[MAXN];
vector< vector<int> > compnod;
vector< vector< pair<int, int> > > compmuc;
vector<bool> usecomp, usenod;
 
vector< pair<int, int> > st;
 

void push(int a, int b) { st.push_back( make_pair(a, b) ); }
 

void popcomp(int a, int b)
{
    vector<int> noduri;
    vector< pair<int, int> > muchii;
 
    noduri.clear(); muchii.clear();
 
    for (; 1; st.pop_back())
    {
        noduri.push_back( st.back().first );
        noduri.push_back( st.back().second );
        muchii.push_back( st.back() );
 
        if ( st.back() == make_pair(a, b) )
        {
            st.pop_back();
            break;
        }
    }
 
    sort(noduri.begin(), noduri.end());
    sort(muchii.begin(), muchii.end());
 
    noduri.resize( unique(noduri.begin(), noduri.end()) - noduri.begin() );
    muchii.resize( unique(muchii.begin(), muchii.end()) - muchii.begin() );
    for (size_t i = 0; i < muchii.size(); i++)
    {
        int a, b;
        for (a = 0; noduri[a] != muchii[i].first; a++);
        for (b = 0; noduri[b] != muchii[i].second; b++);
        muchii[i] = make_pair(a, b);
    }
 
    compnod.push_back( noduri );
    compmuc.push_back( muchii );
    usecomp.push_back( false );        
  
    for (size_t i = 0; i < noduri.size(); i++)
        nodincomp[ noduri[i] ].push_back( (int)compnod.size() - 1 );
}
 

void dfs(int k)
{
    int NCHILD = 0;     
    u[k] = 1;
    low[k] = alt[k];
    vector<int> :: iterator it;
    for (it = con[k].begin(); it != con[k].end(); it++)
    {
        if (!u[*it])
        {
            alt[*it] = alt[k] + 1;
            p[*it] = k;
            push(k, *it);
            dfs(*it);
            NCHILD++;
            if (low[*it] < low[k])
                low[k] = low[*it];
            if (low[*it] >= alt[k])     
            {
                art[k] = 1;
                if (k == 1 && NCHILD < 2)
                    art[k] = 0;
                popcomp(k, *it);   
            }
        }
        else
            if (*it != p[k] && alt[*it] < alt[k])
            {
                push(k, *it);
                if (alt[*it] < low[k])
                    low[k] = alt[*it];
            }
    }
}
 

inline void MARK(int cur)
{
    vector< int > :: iterator it;
    usecomp[cur] = true;
    for (it = compnod[cur].begin(); it != compnod[cur].end(); it++)
        usenod[*it] = true;
}
 

queue<int> Q;
int START, END;                 
vector< bool > hasS, hasD, hasQs;
 
int bfs(int S)
{
    for (; !Q.empty(); Q.pop());
 
    int i;
    vector< int > :: iterator it;
 
    memset(u, -1, sizeof(u));           
    memset(p, -1, sizeof(p));           
    usenod.clear(); usenod.resize(N + 1, false);

    hasS.resize( compnod.size(), false );
    hasD.resize( compnod.size(), false );
    hasQs.resize( compnod.size(), false );
    for (size_t k = 0; k < compnod.size(); k++)
        for (size_t a = 0; a < compnod[k].size(); a++)
        {
            if (compnod[k][a] == S) hasS[k] = true;
            if (compnod[k][a] == D) hasD[k] = true;
            if (compnod[k][a] == Qs) hasQs[k] = true;
        }

    START = -1;
    for (size_t k = 0; k < compnod.size(); k++)
        if ((hasS[k] && hasQs[k]) || (hasD[k] && hasQs[k]))
        {
            START = k;
            break;
        }
 
    if (START == -1)
        return 0;
    int foundS, foundD;
    foundS = hasS[START] ? 1 : 0;
    foundD = hasD[START] ? 1 : 0;
    if (foundS && foundD)
    {
        END = START;
        MARK(START);
        return 1;
    }
 
  
    for (Q.push(START), u[START] = START; !Q.empty() && (!foundS || !foundD); Q.pop())
    {
        i = Q.front();
        for (size_t k = 0; k < compnod[i].size(); k++)
        {
            int n = compnod[i][k];
            for (it = nodincomp[n].begin(); it != nodincomp[n].end(); it++)
            {
                if (u[*it] != -1)
                    continue;
 
                u[*it] = i;
                p[*it] = n;
                Q.push( *it );
                 
	
                if (!foundD && hasD[*it])
                {
                    END = *it;
                    foundD = 1;
                    break;
                }
                if (!foundS && hasS[*it])
                {
                    END = *it;
                    foundS = 1;
                    break;
                }
            }
        }
    }
 
    if (!foundS || !foundD)
        return 0;
 
    for (i = END; i != START; i = u[i])
        MARK(i);
    MARK(START);
    return 1;
}
 
vector<int> DRUM;             
 

int stb[MAXN];
char uc[16], ad[16][16];
int back(int comp, int last, int k)
{
    int i, csz = (int)compnod[comp].size();
    if (k == csz - 2)
    {
        if (last == -1)
        {
            for (i = 0; i < csz; i++)
                if (!uc[i] && ad[ stb[k] ][i])
                    break;
            if (i == csz)
                return 0;
 
            stb[k + 1] = i;
            for (i = 1; i <= k + 1; i++)
                DRUM.push_back( compnod[comp][stb[i]] );
            return 1;
        }
 
        if (ad[ stb[k] ][last])
        {
            stb[k + 1] = last;
            for (i = 1; i <= k + 1; i++)
                DRUM.push_back( compnod[comp][stb[i]] );
            return 1;
        }
        return 0;
    }
 
    int cur = stb[k];
    for (i = 0; i < csz; i++)
    {
        if (uc[i] || !ad[cur][i] || i == last)
            continue;
 
        uc[i] = 1;
        stb[k + 1] = i;
        if (back(comp, last, k + 1))
            return 1;
        uc[i] = 0;
    }
    return 0;
}
 

void makedrum()
{
    vector<int> dr;               
    vector<int> snod;         
 
    int i;
    for (i = END; i != START; i = u[i])
        dr.push_back( i ),
        snod.push_back( p[i] );
    dr.push_back( START );
    snod.push_back( Qs );
 
    reverse( dr.begin(), dr.end() );
    reverse( snod.begin(), snod.end() );
 
    DRUM.push_back( snod[0] );
    for (i = 0; i < (int)dr.size(); i++)
    {
        memset(uc, 0, sizeof(uc));
        memset(ad, 0, sizeof(ad));
        int a, b, cur = dr[i];
        for (a = 0; compnod[cur][a] != snod[i]; a++);
        if (i == (int)dr.size() - 1)
            b = -1;
        else
            for (b = 0; compnod[cur][b] != snod[i + 1]; b++);
 
        for (size_t k = 0; k < compmuc[cur].size(); k++)
        {
            int a = compmuc[cur][k].first, b = compmuc[cur][k].second;
            ad[a][b] = ad[b][a] = 1;
        }
        stb[0] = a;
        uc[a] = 1;
        back(dr[i], b, 0);      
    }
 
    for (i = 0; i < (int)DRUM.size(); i++)
        printf("%d ", DRUM[i]);
    printf("\n");
}
 
int main()
{
    freopen("santa.in", "rt", stdin);
    freopen("santa.out", "wt", stdout);
 
    scanf("%d %d", &N, &M);
    for (; M; M--)
    {
        int i, j;
        scanf("%d %d", &i, &j);
 
        con[i].push_back(j);
        con[j].push_back(i);
    }
    scanf("%d %d %d", &S, &D, &Qs);
 
    dfs(1);                
     
    if (!bfs(S))                
    {
        printf("No chance\n");
        return 0;
    }
 
    int NR = 0;
    for (int i = 1; i <= N; i++)
        if (usenod[i])
            NR++;
    printf("%d\n", NR);
    makedrum();
 
    return 0;
}