Cod sursa(job #1728890)

Utilizator andrei.arnautuAndi Arnautu andrei.arnautu Data 13 iulie 2016 20:01:44
Problema Santa Scor 0
Compilator cpp Status done
Runda Lista lui wefgef Marime 5.89 kb
/**
  *  Worg
  */
#include <stack>
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;
FILE *fin = freopen("santa.in", "r", stdin);
FILE *fout = freopen("santa.out", "w", stdout);

const int MAX_N = 1 + 45000;

/*----------------------------*/ /** General stuff */
vector< int > graph[MAX_N];
int N, M;
int S, E, Q;
/*----------------------------*/ /** Must visit */
bool mustVisit[MAX_N], checked[MAX_N];
/*----------------------------*/ /** Biconnected components */
bool criticalNode[MAX_N];
int level[MAX_N], biconnectedDP[MAX_N];

stack< pair< int,int > > Stack;
vector< vector< int > > comps;
vector< int > criticals, aux;
/*----------------------------*/ /** Path */
bool good[MAX_N];
vector< int > path;
/*----------------------------*/

void noChance() {
    printf("No chance\n"); exit(0);
}

void readData() {
    scanf("%d%d", &N, &M);
    for(int i = 1; i <= M; i++) {
        int u, v; scanf("%d%d", &u, &v);
        graph[u].push_back(v); graph[v].push_back(u);
    }
    scanf("%d%d%d", &S, &E, &Q);
}

void mustVisitDFS(int node = S) {
    checked[node] = true;
    if(node == E) {
        mustVisit[node] = true; return;
    }

    for(vector< int >::iterator it = graph[node].begin(); it != graph[node].end(); it++) {
        if(!checked[*it]) {
            mustVisitDFS(*it);
            mustVisit[node] |= mustVisit[*it];
        }
    }
}

void addComponent(pair< int,int > p) {
    pair< int,int > now;
    do {
        now = Stack.top(); Stack.pop();
        aux.push_back(now.first); aux.push_back(now.second);
    }while(now != p);
    sort(aux.begin(), aux.end());
    aux.erase(unique(aux.begin(), aux.end()), aux.end());

    comps.push_back(aux); aux.clear();
    criticals.push_back(p.first);
}

void biconnectedDFS(int node = S, int father = 0) {
    biconnectedDP[node] = level[node];
    for(vector< int >::iterator it = graph[node].begin(); it != graph[node].end(); it++) {
        if(!level[*it] && mustVisit[*it]) {
            level[*it] = level[node] + 1;
            Stack.push(make_pair(node, *it));
            biconnectedDFS(*it, node);
            if(biconnectedDP[*it] >= level[node]) {
                addComponent(make_pair(node, *it));
                criticalNode[node] = true;
            }
        }
    }

    bool already = false;
    for(vector< int >::iterator it = graph[node].begin(); it != graph[node].end(); it++) {
        if(mustVisit[*it]) {
            if(*it == father && !already) {
                already = true;
            } else {
                biconnectedDP[node] = min(biconnectedDP[node], biconnectedDP[*it]);
            }
        }
    }
}

bool Find(vector< int > &vec, int value) {
    for(vector< int >::iterator it = vec.begin(); it != vec.end(); it++) {
        if(*it == value) {
            return true;
        }
    }
    return false;
}

void Orientate() {
    if(comps.size() == 0) {noChance();}

    if(!Find(comps[0], Q)) { /* if maxDamage is not in the first component, then we have to reverse the order of the components */
        for(int i = 0, j = (int)comps.size() - 1; i < j; i++, j--) {
            swap(comps[i], comps[j]); swap(criticals[i], criticals[j]);
        }
    }

    if(!Find(comps[0], Q)) {
        noChance();
    }

    criticals[0] = Q; /* we want to start from Q */
   /* for(int i = 0; i < (int)comps.size(); i++) {
        for(vector< int >::iterator it = comps[i].begin(); it != comps[i].end(); it++) {
            printf("%d ", *it);
        }
        printf("=>%d", criticals[i]);
        printf("\n");
    }*/
}

bool Back(int limit, int current, int node, int last, bool freeFinish) {
    checked[node] = true;
    path.push_back(node);
   // printf("%d %d %d\n", node, last, current);

    if(current == limit) {
        if(freeFinish) {
            return true;
        } else if(node == last) {
            return true;
        }
    } else {
        for(vector< int >::iterator it = graph[node].begin(); it != graph[node].end(); it++) {
            if(good[*it] && !checked[*it] &&// !(limit != current + 1 && *it == last) &&
               Back(limit, current + 1, *it, last, freeFinish)) {
                    return true;
               }
        }
    }

    checked[node] = false;
    path.pop_back();
    return false;
}

void solveComponent(int index, int first, int last, bool freeFinish) {
    for(vector< int >::iterator it = comps[index].begin(); it != comps[index].end(); it++) {
        good[*it] = true; checked[*it] = false;
     //   printf("%d ", *it);
    }
  //  printf("\n");
    if(!good[first]) {
        noChance();
    }
    if(!freeFinish && !good[last]) {
        noChance();
    }

    bool ok = Back((int)comps[index].size(), 1, first, last, freeFinish);
    for(vector<int >::iterator it = comps[index].begin(); it != comps[index].end(); it++) {
        good[*it] = false;
    }

    if(!ok) {
      //  printf("ERROR");
        noChance();
    }
}

void getPath() {
    for(int i = 0; i < (int)comps.size() - 1; i++) {
        solveComponent(i, criticals[i], criticals[i + 1], false);
    }
    solveComponent((int)comps.size() - 1, criticals[(int)comps.size() - 1], 0, true);
}

void writeData() {
    int Count = (int)path.size();
    for(int i = 0; i < (int)path.size(); i++) {
        if(i > 0 && path[i] == path[i - 1]) {
            --Count;
        }
    }
    printf("%d\n", Count);
    for(int i = 0; i < (int)path.size(); i++) {
        if(!i || (path[i] != path[i - 1])) {
            printf("%d ", path[i]);
        }
    }
}

int main() {
    noChance();
    readData();
    mustVisitDFS();
    if(!mustVisit[Q]) {
        noChance();
    }
    level[S] = 1; biconnectedDFS();
    Orientate(); /* maxDamage has to be in the first or the last biconnected component */
    getPath();
    writeData();
    return 0;
}