Pagini recente » Cod sursa (job #1437399) | Cod sursa (job #2684899) | Cod sursa (job #2677449) | Cod sursa (job #2153857) | Cod sursa (job #1666922)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stack>
#include <unordered_map>
#include <queue>
using namespace std;
#define mp make_pair
#define pb push_back
#define ll long long
#define maxN 90111
#define maxNodes 16
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
#define mp make_pair
#define pb push_back
#define ll long long
#define Point pair<int, int>
class Buffer {
public:
Buffer(string name, int _dim) {
freopen(name.c_str(), "r", stdin);
dim = _dim;
data.resize(dim + 5);
refill();
}
Buffer& operator>>(int &dest) {
while (!is_digit(data[pos]))
if (++pos == dim)
refill();
dest = 0;
while (is_digit(data[pos])) {
dest = dest * 10 + data[pos] - '0';
if (++pos == dim)
refill();
}
return *this;
}
private:
int dim, pos;
vector<char> data;
bool is_digit(char c) {
return '0' <= c && c <= '9';
}
void refill() {
pos = 0;
memset(&data[0], 0, dim);
fread(&data[0], 1, dim, stdin);
}
};
Buffer fin("santa.in", 1 << 22);
int n, m, i, x, y;
int S, D, Q;
//! for biconnected comp
vector<int> list[maxN];
int lvl[maxN];
int low[maxN];
stack< pair<int, int> > St;
//! for tree
int cnt;
vector<int> adj[maxN];
int last[maxN];
vector<int> nodes[maxN];
//! for way
bool all_good;
bool need_swap = false;
bool us[maxN];
vector<int> way;
bool found = false;
//! for hamilton
bool in_process[maxN];
int bit[maxN];
int prov[maxNodes][1 << maxNodes];
vector<int> act;
vector<int> loc_list[maxNodes];
//! for solution
vector<int> solution;
void dfs_low(int node) {
low[node] = lvl[node];
for (int to : list[node]) {
if (lvl[to]) {
//! return edge
low[node] = min(low[node], lvl[to]);
continue;
}
//! tree edge
St.push(mp(node, to));
lvl[to] = lvl[node] + 1;
dfs_low(to);
low[node] = min(low[node], low[to]);
if (low[to] >= lvl[node]) {
//! new component
cnt++;
while (true) {
auto top = St.top(); St.pop();
if (last[top.first] != cnt) {
adj[top.first].pb(cnt);
adj[cnt].pb(top.first);
nodes[cnt].pb(top.first);
last[top.first] = cnt;
}
if (last[top.second] != cnt) {
adj[top.second].pb(cnt);
adj[cnt].pb(top.second);
nodes[cnt].pb(top.second);
last[top.second] = cnt;
}
if (top == mp(node, to)) break;
}
}
}
}
void dfs_way(int node) {
us[node] = true;
way.pb(node);
if (node == D) {
found = true;
return;
}
for (int to : adj[node])
if (!us[to] && !found)
dfs_way(to);
if (!found) way.pop_back();
}
int compute(int node, int conf) {
int act_bit = bit[node];
if (prov[act_bit][conf]) return prov[act_bit][conf];
prov[act_bit][conf] = -1;
if ( (conf & (1 << act_bit)) == 0 ) return -1;
for (int to_id : loc_list[act_bit]) {
int to = act[to_id];
if (compute(to, conf ^ (1 << act_bit)) != -1) {
prov[act_bit][conf] = bit[to] + 1;
break;
}
}
return prov[act_bit][conf];
}
void add_solution(int id, int S, int D) {
int target;
vector<int> local_way;
bool dontknow = false;
act = nodes[id];
target = (1 << act.size()) - 1;
//! precompute some stuff
for (int i = 0; i < (int)act.size(); i++) {
bit[act[i]] = i;
in_process[act[i]] = true;
}
for (int n1 : act) {
loc_list[bit[n1]].clear();
for (int n2 : list[n1])
if (in_process[n2])
loc_list[bit[n1]].pb(bit[n2]);
}
//! set the start position
S = bit[S];
memset(prov, 0, sizeof(prov));
prov[S][ 1 << S ] = S + 1;
if (D == 0) {
//! destionation is irrelevant
//! find a good one
dontknow = true;
for (int e : act) {
if (compute(e, target) != -1) {
D = e;
break;
}
}
} else {
//! just compute it
compute(D, target);
}
//! test if the solution is valid
if (D == 0 || prov[ bit[D] ][target] == -1) {
printf("No chance");
cerr << "No chance\n";
exit(0);
}
//! roll back on your way
D = bit[D];
local_way.clear();
local_way.pb( act[D] );
while (target ^ (1 << D)) {
int aux = prov[D][target] - 1;
target ^= (1 << D);
D = aux;
local_way.pb( act[D] );
}
reverse(local_way.begin(), local_way.end());
if(!dontknow) local_way.pop_back();
for (int e : local_way)
solution.pb(e);
for (int i = 0; i < (int)act.size(); i++)
in_process[act[i]] = false;
}
int main()
{
//freopen("santa.in","r",stdin);
freopen("santa.out","w",stdout);
fin >> n >> m;
for (i = 1; i <= m; i++) {
fin >> x >> y;
list[x].pb(y);
list[y].pb(x);
}
fin >> S >> D >> Q;
//! compute edges between components and nodes
lvl[1] = 1;
cnt = n;
dfs_low(1);
//! check if there are any solutions
bool all_good = false;
for (i = n + 1; i <= cnt; i++) {
bool is_S = false;
bool is_D = false;
bool is_Q = false;
for (int e : nodes[i]) {
is_S |= (e == S);
is_D |= (e == D);
is_Q |= (e == Q);
}
all_good |= is_Q && is_S;
all_good |= is_Q && is_D;
if (is_Q && is_D) need_swap = true;
if (is_Q && is_D && is_S) need_swap = (D == Q);
if (all_good) break;
}
if (!all_good) {
printf("No chance");
cerr << "No chance\n";
return 0;
}
if (need_swap) swap(S, D);
//! now get the way through biconnected components
n = cnt;
dfs_way(Q);
//! solve each component (solve the last one at the final)
for (i = 1; i + 2 < (int)way.size(); i += 2)
add_solution(way[i], way[i - 1], way[i + 1]);
//! the last one is special ... you don't know the destination
add_solution(way[ way.size() - 2 ], way[ way.size() - 3 ], 0);
//! print solution
printf("%d\n", (int)solution.size());
for (int e : solution)
printf("%d ", e);
return 0;
}