#include <bits/stdc++.h>
using namespace std;
/// OBS: Fiecare comp biconexa are cel mult 15 noduri !!!
const int NR_MAX = 16, ST_MAX = 1 << NR_MAX;
int S, E, Q;
const int INF = 1e9 + 5;
vector<bool> visited;
vector<vector<int> > G;
vector<int> level, low;
stack<int> Stack;
vector<bool> isCriticalNode;
vector<pair<int, int> > criticalEdges;
vector<vector<int> > biconex;
vector<int> comp;
void SetInput(string name)
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
(void)!freopen((name + ".in").c_str(), "r", stdin);
(void)!freopen((name + ".out").c_str(), "w", stdout);
}
void FinishProgram()
{
cout << "No chance\n";
exit(0);
}
void DFS_CB(int v, int t, int root) /// Pentru a calcula comp biconexe
{
visited[v] = true;
low[v] = level[v] = level[t] + 1;
Stack.push(v);
int nrChildren = 0;
for(const int u : G[v])
if(u != t)
{
if(visited[u])
{
low[v] = min(low[v], level[u]);
continue;
}
DFS_CB(u, v, root);
low[v] = min(low[v], low[u]);
nrChildren++;
if(v != root && level[v] <= low[u])
isCriticalNode[v] = true;
if(level[v] < low[u])
criticalEdges.emplace_back(v, u);
if(level[v] <= low[u])
{
biconex.push_back(vector<int>(0));
int x;
do{
x = Stack.top();
Stack.pop();
biconex[biconex.size() - 1].push_back(x);
comp[x] = biconex.size() - 1;
} while(x != u);
biconex[biconex.size() - 1].push_back(v);
comp[v] = biconex.size() - 1;
}
}
if(v == root && nrChildren >= 2)
isCriticalNode[root] = true;
}
vector<int> crPath, path;
vector<int> crCriticalNodesInPath, criticalNodesInPath;
vector<bool> visited_2;
void DFS(int v) /// Pentru a calcula prin ce comp biconexe trece drumul de la S la E
{
visited_2[v] = true;
crPath.push_back(comp[v]);
if(v == E)
{
path = crPath;
criticalNodesInPath = crCriticalNodesInPath;
return;
}
for(const int u : G[v])
if(not visited_2[u])
{
if(comp[v] != comp[u]) crCriticalNodesInPath.push_back(v);
DFS(u);
if(comp[v] != comp[u]) crCriticalNodesInPath.pop_back();
}
crPath.pop_back();
}
vector<int> answer;
struct HamiltonianNode
{
bool possible;
int lastNode;
HamiltonianNode() { }
HamiltonianNode(bool _possible, int _last) :
possible(_possible), lastNode(_last) { }
};
HamiltonianNode dp[ST_MAX][16]; /// dp[mask][v] daca se poate face un drum hamiltonian care se termina cu v cu nodurile din mask
unordered_map<int, int> nodeId;
unordered_map<int, int> revNodeId;
void AddToAns(int first, int crr, int mask)
{
if(crr == first)
return;
// cerr << crr << ' ' << dp[mask][nodeId[crr]].lastNode << ' ' << mask << '\n';
AddToAns(first, dp[mask][crr].lastNode, (mask ^ (1 << crr)));
answer.push_back(revNodeId[crr]);
}
void FindPathInCompBiconex(int id, int first, int last)
{
int cnt = biconex[id].size();
int maxMask = (1 << cnt) - 1;
nodeId.clear();
for(int i = 0; i < biconex[id].size(); i++)
{
int u = biconex[id][i];
nodeId[u] = i;
revNodeId[i] = u;
}
for(int mask = 0; mask <= maxMask; mask++)
for(int i = 0; i < cnt; i++)
dp[mask][i] = HamiltonianNode(false, -1);
dp[1 << nodeId[first]][nodeId[first]] = HamiltonianNode(true, -1);
for(int mask = 0; mask < maxMask; mask++)
for(int i = 0; i < cnt; i++)
{
if(not dp[mask][i].possible)
continue;
for(const int u : G[revNodeId[i]])
if(nodeId.count(u) != 0 && (mask & (1 << nodeId[u])) == 0)
dp[mask ^ (1 << nodeId[u])][nodeId[u]] = HamiltonianNode(true, i);
}
if(last != -1)
{
if(not dp[maxMask][nodeId[last]].possible)
FinishProgram();
AddToAns(nodeId[first], last, maxMask);
}
else
{
for(int i = 0; i < cnt; i++)
if(dp[maxMask][i].possible)
{
AddToAns(nodeId[first], i, maxMask);
return;
}
FinishProgram();
}
}
void Solve()
{
int N, M;
cin >> N >> M;
G.resize(N + 1);
visited.resize(N + 1, false);
isCriticalNode.resize(N + 1, false);
level.resize(N + 1, INF);
low.resize(N + 1, INF);
comp.resize(N + 1, -1);
for(int i = 1, u , v; i <= M; i++)
{
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
cin >> S >> E >> Q;
DFS_CB(S, 0, S);
if(not visited[S]) /// Nu exista un drum de la S la E
FinishProgram();
if(find(biconex[comp[S]].begin(), biconex[comp[S]].end(), Q) == biconex[comp[S]].end()) /// S si Q NU sunt in aceeasi comp biconexa
FinishProgram();
visited_2.resize(N + 1, false);
DFS(S);
path.erase(unique(path.begin(), path.end()), path.end());
criticalNodesInPath.insert(criticalNodesInPath.begin(), Q);
answer.push_back(Q);
for(int i = 0; i < path.size(); i++)
if(i == path.size() - 1)
FindPathInCompBiconex(path[i], criticalNodesInPath[i], -1);
else
FindPathInCompBiconex(path[i], criticalNodesInPath[i], criticalNodesInPath[i+1]);
cout << answer.size() << '\n';
for(int v : answer)
cout << v << ' ';
}
int main()
{
SetInput("santa");
Solve();
return 0;
}