Cod sursa(job #782655)

Utilizator valentin.harsanValentin Harsan valentin.harsan Data 28 august 2012 15:49:14
Problema Santa Scor 0
Compilator cpp Status done
Runda Lista lui wefgef Marime 5.51 kb
#include<fstream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;

ifstream in("santa.in");
ofstream out("santa.out");

const int N = 90100;

int n, m, nrc, niv[N], nivmin[N], st1[N], st2[N], u, sol[20];
bool crit[N], con[20][20], ut[20];

int S, E, Q, pozS, pozQ, pozE;
bool vS[N], vQ[N], vE[N];

int st, fin, p[N], ss;

vector<int> v[N], cb[N], arbcb[N], path, comp[N], Rez;
bool viz[N];

void add(int nod, int p) {
    int x, y;

    ++nrc;
    do {
        x=st1[u];
        y=st2[u--];

        cb[nrc].push_back(y);
        comp[y].push_back(nrc);
    } while(x!=nod || y!=p);

    cb[nrc].push_back(x);
    comp[x].push_back(nrc);
}

void c_bi(int nod, int p) {
    vector<int>::iterator it;
    viz[nod] = true; niv[nod] = nivmin[nod] = niv[p] + 1;

    for(it = v[nod].begin(); it != v[nod].end(); ++it) if(*it != p) {

        if(!viz[*it]) {
            st1[++u] = nod;
            st2[u] = *it;

            c_bi(*it, nod);

            if(nivmin[*it] < nivmin[nod])
                nivmin[nod] = nivmin[*it];

            if(nivmin[*it] >= niv[nod]) {
                if(nod != 1) crit[nod] = true;
                add(nod, *it);
            }

        }
        else if(nivmin[nod] > nivmin[*it])
            nivmin[nod] = nivmin[*it];
    }
}

bool drum() {
    int i, j;
    queue<int> q;

    for(i = 1; i<=n; ++i) if(crit[i])
        for(j = 0; j!=comp[i].size(); ++j) {
            arbcb[i + nrc + 1].push_back(comp[i][j]);
            arbcb[comp[i][j]].push_back(i + nrc + 1);
        }

    for(i = 1; i<=nrc; ++i)
        for(j = 0; j != cb[i].size(); ++j) {

            if(cb[i][j] == S)
                pozS = i, vS[i] = true;
            if(cb[i][j] == E)
                pozE = i, vE[i] = true;
            if(cb[i][j] == Q)
                pozQ = i, vQ[i] = true;
        }

    if(pozS == pozQ) {
        st = pozS;
        if(crit[Q])
            st = S + nrc + 1;
        fin = pozE;
        if(crit[E])
            fin = E + nrc + 1;
    }
    if(pozE == pozQ) {
        st = pozE;
        if(crit[Q])
            st = E + nrc + 1;
        fin = pozS;
        if(crit[S])
            fin = S + nrc + 1;
    }

    if(!st)
        return 0;

    if(Q == E && crit[Q]) {
        st = E + nrc + 1;
        fin = pozS;
        if(crit[S])
            fin = S + nrc + 1;
    }
    if(Q == S && crit[S]) {
        st = S + nrc + 1;
        fin = pozE;
        if(crit[E])
            fin = E + nrc + 1;
    }

    q.push(st); p[st] = -1;

    while(!q.empty()) {
        int el = q.front();
        q.pop();
        for(vector<int>::iterator it = arbcb[el].begin(); it!=arbcb[el].end(); ++it) if(!p[*it]) {

            p[*it] = el;
            q.push(*it);
        }
    }

    int t = fin;
    path.push_back(t);
    while(t != st) {
        t = p[t];
        path.push_back(t);
    }

    reverse(path.begin(), path.end());

    return true;
}

int back(int nod, int comp, int f, int pas) {
    int i;

    if(pas == cb[comp].size() - 1) {

        if(con[sol[pas - 1]][f]) {

            for(i = 1; i!=pas; ++i)
                Rez.push_back(cb[comp][sol[i]]);
            Rez.push_back(cb[comp][f]);
            return 1;
        }
        else {

            if(f)
                return false;

            for(i = 0; i != cb[comp].size(); ++i)
                if(!ut[i] && con[sol[pas - 1]][i])
                    break;
            if(i == cb[comp].size())
                return false;

            for(i = 1; i!=pas; ++i)
                Rez.push_back(cb[comp][sol[i]]);
                Rez.push_back(cb[comp][i]);
            return true;
        }
    }

    for(i = 0; i != cb[comp].size(); ++i) if(!ut[i] && con[nod][i] && i != f) {
        ut[i] = true;
        sol[pas] = i;

        if(back(i, comp, f, pas + 1))
            return 1;
        ut[i] = false;
    }
    return false;
}

void calcDrum() {
    int last = Q, fin;

    Rez.push_back(Q);

    for(vector<int>::iterator it = path.begin(); it != path.end(); ++it) {

        if(*it > nrc) {
            last = *it - nrc - 1;
            continue;
        }

        memset(con, 0, sizeof(con));
        memset(ut, 0, sizeof(ut));

        for(int i = 0; i != cb[*it].size(); ++i)
            for(int j = 0; j != cb[*it].size(); ++j)
                for(vector<int>::iterator k = v[cb[*it][i]].begin(); k != v[cb[*it][i]].end(); ++k)
                    if((*k) == cb[*it][j])
                        con[i][j] = con[j][i] = true;

        fin = *(it + 1);

        for(int i = 0; i != cb[*it].size(); ++i)
            if(cb[*it][i] == last) {
                last = i;
                break;
            }
        for(int i = 0; i!=cb[*it].size(); ++i)
            if(cb[*it][i] == fin - nrc - 1) {
                fin = i;
                break;
            }

        ut[last] = true;

        if(it == path.end() - 1)
            back(last, *it, 0, 1);
        else
            back(last, *it, fin, 1);

        last = 0;
    }
}

int main() {
    int i, a, b;

    in >> n >> m;

    for(i = 1; i<=n; ++i) {
        in >> a >> b;

        v[a].push_back(b);
        v[b].push_back(a);
    }

    in >> S >> E >> Q;

    c_bi(1, 0);

    if(!drum()) {
        out << "No chance\n";
        return 0;
    }

    calcDrum();

    out << Rez.size() << "\n";
    for(i = 0; i!=Rez.size(); ++i)
        out << Rez[i] << " ";

    return 0;
}