#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <cassert>
#include <stack>
#include <cstring>
using namespace std;
ifstream f("santa.in");
ofstream g("santa.out");
int N, M, T;
int CntComponents, CntCritical;
int S, E, Q;
vector< vector<int> > G;
vector< vector<int> > Tree;
vector<int> Level, LowPoint, WComponent, WCritical;
vector<bool> IsCritical;
vector<int> Critical, CountComponents;
vector< vector<int> > Components;
vector<int> Path, Itinerary;
vector<int> Pos, IsHere;
vector<int> ANS;
bool solution=1;
stack< pair<int, int> > Stack;
void Read ()
{
f >> N >> M;
G.resize(N);
Level.resize(N, 0);
LowPoint.resize(N, 0);
WComponent.resize(N, 0);
IsCritical.resize(N, 0);
WCritical.resize(N, 0);
Pos.resize(N, 0);
IsHere.resize(N, 0);
CountComponents.resize(N, 0);
for (int i=0; i<M; i++)
{
int a, b;
f >> a >> b;
G[a-1].push_back(b-1);
G[b-1].push_back(a-1);
}
f >> S >> E >> Q;
S--;
E--;
Q--;
}
void DF (int node, int father)
{
LowPoint[node]=Level[node];
for (vector<int>::iterator it=G[node].begin(); it!=G[node].end(); ++it)
{
if (*it==father)
continue;
if (Level[*it]==0)
{
Level[*it]=Level[node]+1;
Stack.push(make_pair(node, *it));
DF(*it, node);
LowPoint[node]=min(LowPoint[node], LowPoint[*it]);
if (LowPoint[*it]>=Level[node])
{
vector<int> Aux;
Aux.clear();
for (; !Stack.empty() && Stack.top()!=make_pair(node, *it); Stack.pop())
{
Aux.push_back(Stack.top().first);
Aux.push_back(Stack.top().second);
}
if (!Stack.empty() && Stack.top()==make_pair(node, *it))
{
Aux.push_back(Stack.top().first);
Aux.push_back(Stack.top().second);
Stack.pop();
}
sort(Aux.begin(), Aux.end());
Aux.resize(unique(Aux.begin(), Aux.end()) - Aux.begin());
assert(Aux.size()<=20);
for (int i=0; i<Aux.size(); i++)
CountComponents[Aux[i]]++;
Components.push_back(Aux);
}
}
else
LowPoint[node]=min(LowPoint[node], Level[*it]);
}
}
void DoBiconnected ()
{
for (int i=0; i<N; i++)
if (Level[i]==0)
{
Level[i]=1;
DF(i, -1);
}
for (int i=0; i<N; i++)
if (CountComponents[i]>=2)
{
Critical.push_back(i);
IsCritical[i]=1;
}
sort(Critical.begin(), Critical.end());
Critical.resize(unique(Critical.begin(), Critical.end()) - Critical.begin());
for (vector<int>::iterator it=Critical.begin(); it!=Critical.end(); ++it)
WCritical[*it]=it - Critical.begin();
CntCritical=Critical.size();
CntComponents=Components.size();
T=CntCritical + CntComponents;
Tree.resize(T);
for (int i=0; i<Components.size(); i++)
for (vector<int>::iterator it=Components[i].begin(); it!=Components[i].end(); ++it)
if (IsCritical[*it]==1)
{
Tree[CntComponents + WCritical[*it]].push_back(i);
Tree[i].push_back(CntComponents + WCritical[*it]);
}
else
WComponent[*it]=i;
}
bool DFTree (int node, int father, int end)
{
Path.push_back(node);
if (node==end)
return 1;
bool found=0;
for (vector<int>::iterator it=Tree[node].begin(); it!=Tree[node].end(); ++it)
if (*it!=father)
{
found|=DFTree(*it, node, end);
if (found)
return 1;
}
Path.pop_back();
return 0;
}
int DP[50000][16];
int Back[50000][16];
void DoHamilton (int hash, int start, vector<int>& V, int end)
{
int n=V.size();
//assert(n<=20);
for (int i=0; i<n; i++)
{
Pos[V[i]]=i;
IsHere[V[i]]=hash;
}
for (int i=0; i<n; i++)
if (V[i]==start)
{
start=i;
break;
}
bool E[n][n];
memset(E, 0, sizeof(E));
for (int i=0; i<n; i++)
for (vector<int>::iterator it=G[V[i]].begin(); it!=G[V[i]].end(); ++it)
if (IsHere[*it]==hash)
E[i][Pos[*it]]=1;
DP[1 << start][start]=hash;
for (int i=0; i<(1 << n); i++)
for (int j=0; j<n; j++)
if ((i&(1 << j))!=0 && DP[i][j]==hash)
for (int k=0; k<n; k++)
if (E[j][k]==1 && ((1 << k)&i)==0 && DP[i|(1 << k)][k]!=hash)
{
DP[i|(1 << k)][k]=hash;
Back[i|(1 << k)][k]=j;
}
int i=(1 << n)-1;
int j=end;
int k;
for (k=0; k<n; k++)
if (V[k]==end)
{
j=k;
break;
}
if (j==-1)
{
for (k=0; k<n; k++)
if (DP[i][k]==hash)
{
j=k;
break;
}
}
if (j==-1 || DP[i][j]!=hash)
{
solution=false;
return;
}
vector<int> aux;
while (j!=start && DP[i][j]==hash)
{
aux.push_back(j);
k=i;
i-=(1 << j);
if (j==Back[k][j])
break;
j=Back[k][j];
}
aux.push_back(start);
for (int i=aux.size()-1; i>=0; i--)
ANS.push_back(V[aux[i]]);
}
void Go ()
{
for (int i=1; i<Itinerary.size(); i+=2)
DoHamilton(i, Itinerary[i-1], Components[Itinerary[i]], Itinerary[i+1]);
}
void FindPath ()
{
int start, end;
if (IsCritical[S])
start=CntComponents + WCritical[S];
else
start=WComponent[S];
if (IsCritical[E])
end=CntComponents + WCritical[E];
else
end=WComponent[E];
DFTree(start, -1, end);
int first=-1, last=-1;
for (vector<int>::iterator it=Path.begin(); it!=Path.end(); ++it)
if (*it<CntComponents)
{
first=*it;
break;
}
for (vector<int>::reverse_iterator it=Path.rbegin(); it!=Path.rend(); ++it)
if (*it<CntComponents)
{
last=*it;
break;
}
if (first<0 || last<0)
return;
bool found=0;
for (vector<int>::iterator it=Components[first].begin(); it!=Components[first].end(); ++it)
if (*it==Q)
{
found=1;
break;
}
if (found)
{
for (int i=0; i<Path.size(); i++)
if (Path[i]==first)
{
Itinerary.push_back(Q);
for (int j=i; j<Path.size(); j++)
if (Path[j]<CntComponents)
Itinerary.push_back(Path[j]);
else
Itinerary.push_back(Critical[Path[j] - CntComponents]);
if (Itinerary.size()%2==1)
Itinerary[Itinerary.size()-1]=-1;
if (Itinerary.size()%2==0)
Itinerary.push_back(-1);
Go();
return;
}
return;
}
for (vector<int>::iterator it=Components[last].begin(); it!=Components[last].end(); ++it)
if (*it==Q)
{
found=1;
break;
}
if (found)
{
for (int i=Path.size()-1; i>=0; i--)
if (Path[i]==last)
{
Itinerary.push_back(Q);
for (int j=i; j>=0; j--)
if (Path[j]<CntComponents)
Itinerary.push_back(Path[j]);
else
Itinerary.push_back(Critical[Path[j] - CntComponents]);
if (Itinerary.size()%2==1)
Itinerary[Itinerary.size()-1]=-1;
if (Itinerary.size()%2==0)
Itinerary.push_back(-1);
Go();
return;
}
return;
}
}
void Print ()
{
vector<int> aux;
for (int i=0; i<ANS.size(); i++)
if (i==0)
aux.push_back(ANS[i]);
else
if (ANS[i]!=ANS[i-1])
aux.push_back(ANS[i]);
if (aux.size()==0 || solution==false)
g << "No chance\n";
else
{
g << aux.size() << '\n';
for (int i=0; i<aux.size(); i++)
g << aux[i]+1 << ' ';
g << '\n';
}
}
int main ()
{
Read();
DoBiconnected();
FindPath();
Print();
f.close();
g.close();
return 0;
}