#include <fstream>
#include <iostream>
#include <cassert>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
constexpr int INF = 1e9;
constexpr int NIL = -1;
template<class T> using vec = std::vector<T>;
bool has( const std::pair<int, int> p, int x ) { return p.first == x || p.second == x; }
int other( const std::pair<int, int> p, int x ) { assert( has( p, x ) ); return p.first + p.second - x; }
int common( const std::pair<int, int> A, const std::pair<int, int> B ) {
return A.first * has( B, A.first ) + A.second * has( B, A.second );
}
vec<vec<int>> get_biconex( const vec<vec<int>> &adj, const vec<std::pair<int, int>> &edges ) {
int n = (int)adj.size();
vec<vec<int>> ret; {
vec<bool> viz(n, false);
vec<int> edge_stack;
int time = 0;
vec<int> t(n, 0);
auto dfs = [&]( auto &&self, int u, int p ) -> int {
t[u] = time++;
int reach = t[u];
viz[u] = true;
for( int edge : adj[u] ){
int v = other( edges[edge], u );
if( !viz[v] ){
edge_stack.push_back( edge );
int reach_v = self( self, v, u );
reach = std::min( reach, reach_v );
if( reach_v >= t[u] ){
ret.emplace_back();
do{
ret.back().push_back( edge_stack.back() );
edge_stack.pop_back();
}while( ret.back().back() != edge );
}
}else if( v != p && t[v] < t[u] ){
reach = std::min( reach, t[v] );
edge_stack.push_back( edge );
}
}
return reach;
};
for( int i = 0; i < n; i++ )
if( !viz[i] ){
dfs( dfs, i, i );
assert( edge_stack.empty() );
}
}
return ret;
}
vec<int> hamilton( int n, vec<std::pair<int, int>> edges, int src, int dest ) {
if( n == 1 ) return vec<int>(1, src);
if( n == 2 ) return vec<int>({ src, other( edges[0], src ) });
// truc: src si dest devin n - 1, n - 2
bool rem_last = false;
if( dest == NIL ){
for( int i = 0; i < n; i++ )
edges.emplace_back( i, n );
dest = n++;
rem_last = true;
}
vec<int> encode(n), decode(n); {
for( int i = 0; i < n; i++ )
encode[i] = decode[i] = i;
int x = decode[n - 1];
std::swap( encode[src], encode[x] );
std::swap( decode[encode[src]], decode[encode[x]] );
int y = decode[n - 2];
std::swap( encode[dest], encode[y] );
std::swap( decode[encode[dest]], decode[encode[y]] );
src = encode[src];
dest = encode[dest];
assert( src == n - 1 && dest == n - 2 );
}
vec<vec<int>> adj(n); {
for( auto [a, b]: edges ){
adj[encode[a]].push_back( encode[b] );
adj[encode[b]].push_back( encode[a] );
}
}
int small = n - 2;
int small_p2 = (1 << small);
vec<int> prev(small * small_p2, NIL);
for( int v : adj[src] )
if( v < small )
prev[(1 << v) * small + v] = src;
{// mica optimizare
for( int i = 0; i < small; i++ )
adj[i].erase( std::remove_if( adj[i].begin(), adj[i].end(), [&]( int x ) -> bool { return x >= small; } ), adj[i].end() );
}
for( int mask = 0; mask < small_p2; mask++ ){
for( int a = 0; a < small; a++ ){
if( !(mask & (1 << a)) ) continue;
if( prev[mask * small + a] == NIL ) continue;
for( int b : adj[a] )
if( !(mask & (1 << b)) )
prev[(mask | (1 << b)) * small + b] = a;
}
}
int last = NIL; {
for( int v : adj[dest] )
if( v < small && prev[(small_p2 - 1) * small + v] != NIL )
last = v;
}
if( last == NIL ) return {};
int mask = small_p2 - 1;
vec<int> ret({ dest, last });
while( ret.back() != src ){
int P = prev[mask * small + ret.back()];
mask &= ~(1 << ret.back());
ret.push_back( P );
}
assert( (int)ret.size() == n );
std::reverse( ret.begin(), ret.end() );
for( int &u : ret ) u = decode[u];
if( rem_last ) ret.pop_back();
return ret;
}
vec<int> get_path( std::ifstream &fin ) {
int n, m;
fin >> n >> m;
vec<std::pair<int, int>> edges;
vec<vec<int>> adj(n); {
for( int i = 0; i < m; i++ ){
int a, b;
fin >> a >> b;
edges.emplace_back( --a, --b );
adj[a].push_back( i );
adj[b].push_back( i );
}
}
int src, dest, path_begin;
fin >> src >> dest >> path_begin;
src--; dest--; path_begin--;
if( src == dest ) {
if( src != path_begin ) return {};
return vec<int>(1, src);
}
vec<vec<int>> biconexe = get_biconex( adj, edges );
vec<int> edge2bi(m); {
for( int i = 0; i < (int)biconexe.size(); i++ )
for( int u : biconexe[i] )
edge2bi[u] = i;
}
vec<int> path; {
vec<int> dist(n, +INF);
vec<int> prev(n);
std::queue<int> q({ src });
dist[src] = 0;
while( !q.empty() ){
int u = q.front();
q.pop();
for( int edge : adj[u] ){
int v = other( edges[edge], u );
if( dist[u] + 1 < dist[v] ){
dist[v] = 1 + dist[u];
prev[v] = edge;
q.push( v );
}
}
}
int u = dest;
if( dist[u] >= +INF ) return {};
while( u != src ){
path.push_back( prev[u] );
u = other( edges[prev[u]], u );
}
std::reverse( path.begin(), path.end() );
}
vec<int> bis(1, edge2bi[path[0]]);
vec<int> transitions;
for( int i = 1; i < (int)path.size(); i++ ){
if( edge2bi[path[i - 1]] == edge2bi[path[i]] ) continue;
bis.push_back( edge2bi[path[i]] );
transitions.push_back( common( edges[path[i - 1]], edges[path[i]] ) );
}
assert( (int)bis.size() - 1 == (int)transitions.size() );
auto bi_has = [&]( int bi, int u ) -> bool {
bool ret = false;
for( int edge : biconexe[bi] )
ret |= has( edges[edge], u );
return ret;
};
if( bi_has( bis.front(), path_begin ) ){
transitions.insert( transitions.begin(), path_begin );
transitions.push_back( NIL );
}else if( bi_has( bis.back(), path_begin ) ){
std::reverse( transitions.begin(), transitions.end() );
std::reverse( bis.begin(), bis.end() );
transitions.insert( transitions.begin(), path_begin );
transitions.push_back( NIL );
}else
return {};
assert( (int)bis.size() + 1 == (int)transitions.size() );
assert( transitions.back() == NIL );
auto viz_all = [&]( int bi, int src, int dest ) -> vec<int> {
assert( bi_has( bi, src ) );
assert( dest == NIL || bi_has( bi, dest ) );
vec<int> wide;
std::map<int, int> narrow; {
for( int edge : biconexe[bi] ){
auto [a, b] = edges[edge];
narrow[a] = narrow[b] = 1;
}
for( auto &[key, val]: narrow ){
val = (int)wide.size();
wide.push_back( key );
}
}
vec<std::pair<int, int>> narrow_edges;
for( int edge : biconexe[bi] ){
auto [a, b] = edges[edge];
narrow_edges.emplace_back( narrow[a], narrow[b] );
}
vec<int> narrow_path = hamilton( (int)wide.size(), narrow_edges, narrow[src], (dest == NIL ? NIL : narrow[dest]) );
for( int &u : narrow_path ) u = wide[u];
return narrow_path; // acuma wide
};
vec<int> ret;
for( int i = 0; i < (int)bis.size(); i++ ){
vec<int> seg = viz_all( bis[i], transitions[i], transitions[i + 1] );
if( seg.empty() ) return {};
if( ret.empty() ){
ret = seg;
continue;
}
assert( ret.back() == seg.front() );
ret.insert( ret.end(), seg.begin() + 1, seg.end() );
}
return ret;
}
int main() {
std::ifstream fin("santa.in");
std::ofstream fout("santa.out");
vec<int> path = get_path( fin );
if( path.empty() ){
fout << "No chance\n";
return 0;
}
fout << path.size() << '\n';
for( int x : path )
fout << x + 1 << ' ';
fout << '\n';
return 0;
}