#include <fstream>
#include <vector>
#include <stack>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const bool DEBUG = true;
const int B_MAX = 20;
const int MAX = 45005;
int N, M, S, End, Q;
int Level[MAX], highest[MAX], componentIndex[MAX], Idx[MAX], B[B_MAX];
int edgeExists[B_MAX][B_MAX];
bool ok;
bool isCritical[MAX], isEnding[MAX], Used[MAX];
vector<int> G[MAX], V[MAX], E[MAX], Drum, miniPath, Path;
vector< vector<int> > Components;
stack< pair<int, int> > stk;
void citire() {
ifstream in("santa.in");
in >> N >> M;
for(int i = 1, A, B; i <= M; i++) {
in >> A >> B;
G[A].push_back(B);
G[B].push_back(A);
} in >> S >> End >> Q;
in.close();
}
void getBiconnectedComponent(int X, int Y) {
vector<int> Component;
int x, y;
do {
x = stk.top().first, y = stk.top().second;
stk.pop();
Component.push_back(x); Component.push_back(y);
} while(x != X || y != Y);
sort(Component.begin(), Component.end());
Component.erase(unique(Component.begin(), Component.end()), Component.end());
for(size_t i = 0; i < Component.size(); i++)
componentIndex[ Component[i] ] = Components.size();
Components.push_back(Component);
}
void dfs(int nod, int dad, int level) {
Level[nod] = highest[nod] = level;
int sonCnt = 0, critic = 0;
for(size_t i = 0; i < G[nod].size(); i++) {
int dest = G[nod][i];
if(dest == dad) continue;
if(!Level[dest]) {
sonCnt++;
stk.push( make_pair(nod, dest) );
dfs(dest, nod, level + 1);
highest[nod] = min(highest[nod], highest[dest]);
if(highest[dest] >= Level[nod]) {
getBiconnectedComponent(nod, dest);
critic = 1;
}
} else highest[nod] = min(highest[nod], Level[dest]);
}
if(!DEBUG && nod == 1) cerr << sonCnt << "\n";
if(nod == dad)
isCritical[nod] = (sonCnt > 1);
else isCritical[nod] = critic;
}
void getBiconnectedComponents() {
for(int i = 1; i <= N; i++)
if(!Level[i]) dfs(i, i, 1);
for(int i = 1; i <= N; i++)
if(isCritical[i])
componentIndex[i] = -1;
}
bool validGraph() {
bool isValid = false;
for(size_t i = 0; i < Components.size(); i++) {
bool QHere = false, SHere = false, EHere = false;
for(size_t j = 0; j < Components[i].size(); j++) {
int nod = Components[i][j];
if(Q == nod) QHere = true;
if(S == nod) SHere = true;
if(End == nod) EHere = true;
}
if(QHere && (SHere || EHere)) isValid = true;
isEnding[i] = EHere;
} return isValid;
}
bool canReachEnd(int nod, int dad) {
Drum.push_back(nod);
//cerr << nod << " ";
if((nod == End) || (nod > N && isEnding[nod - N - 1])) return true;
for(size_t i = 0; i < V[nod].size(); i++) {
int dest = V[nod][i];
//cerr << dest << "\n";
if(dest == dad) continue;
if(canReachEnd(dest, nod)) return true;
} Drum.pop_back();
return false;
}
void buildGraph(const int &Component) {
for(size_t i = 0; i < Components[ Component ].size(); i++)
Idx[ Components[ Component ][ i ] ] = i;
for(size_t i = 0; i < Components[ Component ].size(); i++) {
int nod = Components[ Component ][ i ];
for(size_t j = 0; j < G[nod].size(); j++) {
int dest = G[nod][j];
if(Idx[dest] != -1) {
E[ Idx[nod] ].push_back( Idx[dest] );
edgeExists[ Idx[nod] ][ Idx[dest] ] = true;
}
}
}
}
void eraseGraph(const int &Component) {
for(size_t i = 0; i < Components[ Component ].size(); i++) {
int nod = Components[ Component ][ i ];
E[i].clear();
Idx[nod] = -1;
} memset(edgeExists, 0, sizeof(edgeExists));
}
bool Back(int lastNode, const int &Component, const int &Finish) {
int nod = B[lastNode];
if(lastNode == (int)Components[ Component ].size() - 1) {
if(Finish == -1) {
bool isValid = false;
for(size_t i = 0; i < E[nod].size(); i++) {
int dest = E[nod][i];
if(!Used[dest]) {
B[lastNode + 1] = dest;
isValid = true;
break;
}
}
if(!isValid) return false;
} else {
if(!edgeExists[ nod ][ Finish ]) return false;
B[lastNode + 1] = Finish;
}
for(int i = 2; i <= lastNode + 1; i++) {
Used[ B[i] ] = false;
miniPath.push_back( Components[ Component ][ B[i] ] );
} return true;
}
for(size_t i = 0; i < E[nod].size(); i++) {
int dest = E[nod][i];
if(Used[dest] || dest == Finish) continue;
B[ lastNode + 1 ] = dest; Used[dest] = true;
if( Back(lastNode + 1, Component, Finish) ) return true;
B[ lastNode + 1 ] = 0; Used[dest] = false;
} return false;
}
void getPathThroughBiconnectedComponent(const int &Component, const int &Start, const int &Stop) {
buildGraph(Component);
miniPath.clear();
int startingNode = Idx[Start], endingNode = (Stop == -1 ? -1 : Idx[Stop]);
B[1] = startingNode; Used[startingNode] = true;
Back(1, Component, endingNode);
B[1] = 0; Used[startingNode] = true;
eraseGraph(Component);
}
bool getPath() {
if(!validGraph()) {
//cerr << "Graph was not valid\n";
return false;
}
int Start = (isCritical[Q] ? Q : componentIndex[Q] + N + 1), Stop;
if(Start > N) Drum.push_back(Q);
if(!canReachEnd(Start, 0)) {
//cerr << "Can't reach end\n";
return false;
}
if(!DEBUG) {
for(size_t i = 0; i < Drum.size(); i++)
cerr << Drum[i] << " ";
cerr << "\n";
}
Path.push_back(Q);
for(size_t i = 0; i < Drum.size(); i++) {
if(Drum[i] <= N) continue;
Start = Drum[i - 1], Stop = (i + 1 < Drum.size() ? Drum[i + 1] : -1);
getPathThroughBiconnectedComponent(Drum[i] - N - 1, Start, Stop);
if( miniPath.empty() ) return false;
for(size_t j = 0; j < miniPath.size(); j++)
Path.push_back(miniPath[j]);
} return true;
}
void buildTree() {
for(size_t i = 0; i < Components.size(); i++)
for(size_t j = 0; j < Components[i].size(); j++) {
int nod = Components[i][j];
if(isCritical[nod]) {
V[nod].push_back(N + i + 1);
V[N + i + 1].push_back(nod);
if(!DEBUG) {
cerr << "ADDED EDGE FROM " << nod << " TO " << N + i + 1 << "\n";
}
}
}
}
void solve() {
getBiconnectedComponents();
if(!DEBUG) {
for(size_t i = 0; i < Components.size(); i++) {
for(size_t j = 0; j < Components[i].size(); j++)
cerr << Components[i][j] << " ";
cerr << "\n";
}
for(int i = 1; i <= N; i++)
if(componentIndex[i] == -1) cerr << i << " ";
}
buildTree();
memset(Idx, -1, sizeof(Idx));
ok = getPath();
}
void afisare() {
ofstream out("santa.out");
if(ok) {
out << Path.size() << "\n";
for(size_t i = 0; i < Path.size(); i++)
out << Path[i] << " ";
out << "\n";
} else out << "No chance\n";
out.close();
}
int main() {
citire();
solve();
afisare();
}