Pagini recente » Cod sursa (job #3344006) | Cod sursa (job #2496869) | Cod sursa (job #3353233) | Cod sursa (job #335272) | Cod sursa (job #3348541)
#include <fstream>
#include <vector>
#include <stack>
#include <bitset>
#include <queue>
using namespace std;
typedef vector<int> vint;
typedef vector<vint> graph;
void reverse(vint& v){
for(int i = 0, j = v.size() - 1; i < j; i++, j--)
swap(v[i], v[j]);
}
void pop_first(vint &path){
for(int i = 1; i < path.size(); i++)
path[i - 1] = path[i];
path.pop_back();
}
const int N_MAX = 45005;
const int TREE_MAX = 2 * N_MAX;
const int SIGMA = 16;
const int ALR_DONE = -2;
const int IMPOSSIBLE = -1;
int n;
graph G;
int elf, santa;
int gica_place;
void read_graph(){
ifstream fin("santa.in");
int m;
fin >> n >> m;
G.resize(n + 1);
while(m--){
int x, y;
fin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
fin >> elf >> santa >> gica_place;
fin.close();
}
int in[N_MAX], lwk[N_MAX];
int stack_[N_MAX], vf;
inline int top(){
return stack_[vf - 1];
}
vint comp_bicon[N_MAX];
int cnt_bicon;
int art_point[N_MAX], cnt_art_points;
int comp_of_node[N_MAX];
vint node_to_art;
graph tree;
bitset<TREE_MAX> seen, allowed;
void create_comp(int node, int son){
cnt_bicon++;
while(top() != son){ // a little trick
comp_bicon[cnt_bicon].push_back(top());
comp_of_node[top()] = cnt_bicon;
vf--;
}
comp_bicon[cnt_bicon].push_back(top());
comp_of_node[top()] = cnt_bicon;
vf--;
comp_bicon[cnt_bicon].push_back(node);
comp_of_node[node] = cnt_bicon;
}
void dfs_bicon(int node, int parent){
static int global_time = 0;
in[node] = lwk[node] = ++global_time;
stack_[vf++] = node;
int sons_bicon = 0;
for(int& son: G[node]){
if(parent == son) continue;
if(in[son]) lwk[node] = min(lwk[node], in[son]);
else{ // hasn't been discovered
dfs_bicon(son, node);
lwk[node] = min(lwk[node], lwk[son]);
if(in[node] <= lwk[son]){ // node is articulation point
sons_bicon++;
create_comp(node, son);
}
}
}
if(sons_bicon >= 2 || (sons_bicon == 1 && parent))
art_point[node] = ++cnt_art_points;
}
void compute_tree_bicon(){
dfs_bicon(1, 0); // breaking into biconected components
// transforming them into nodes
node_to_art.resize(cnt_art_points + 1);
for(int i = 1; i <= n; i++){
if(art_point[i]){
node_to_art[art_point[i]] = i;
art_point[i] += cnt_bicon;
}
}
tree.resize(cnt_bicon + cnt_art_points + 1);
for(int i = 1; i <= cnt_bicon; i++){
for(const int& u: comp_bicon[i]){
if(!art_point[u]) continue;
tree[i].push_back(art_point[u]);
tree[art_point[u]].push_back(i);
}
}
}
inline int graph_to_tree(int x){
return (art_point[x]?
art_point[x]:
comp_of_node[x]
);
}
int elf_tree, santa_tree;
vint tree_path, depth,
final_path, ant;
bool dfs_path(int u){
if(u == santa_tree) return 1;
seen[u] = 1;
for(const int& v: tree[u]){
if(!seen[v] && dfs_path(v)){
tree_path.push_back(v);
return 1;
}
}
return 0;
}
void dfs_depth(int u){
for(const int&v: tree[u]){
if(!depth[v]){
depth[v] = depth[u] + 1;
dfs_depth(v);
}
}
}
queue<int> que;
int append_shortest_path(int tree_node){
// this function will print the sp from gica_place to any node
// that coresponds to the tree_node while printing the last node
// in the path if the last node is an articulation point
depth.resize(n + 1, 0); ant.resize(n + 1, 0);
for(int i = 1; i <= n; i++) depth[i] = 0;
depth[gica_place] = 1;
que.push(gica_place);
while(!que.empty()){
int u = que.front();
que.pop();
for(const int& v: G[u]){
if(!depth[v]){
depth[v] = 1 + depth[u];
ant[v] = u;
que.push(v);
}
}
}
int mark;
if(tree_node > cnt_bicon) mark = node_to_art[tree_node - cnt_bicon];
else{
mark = comp_bicon[tree_node][0];
for(int u: comp_bicon[tree_node])
if(depth[mark] > depth[u]) mark = u;
}
depth[0] = ant[gica_place] = 0;
while(depth[mark]){
final_path.push_back(mark);
mark = ant[mark];
}
reverse(final_path);
return final_path.back();
}
int first_test(){
santa_tree = graph_to_tree(santa);
elf_tree = graph_to_tree(elf);
int gica_tree = graph_to_tree(gica_place);
dfs_path(elf_tree);
tree_path.push_back(elf_tree);
if(tree_path.size() == 1 && tree_path[0] > cnt_bicon){
// elf and santa colide and form an art point
append_shortest_path(tree_path[0]);
return ALR_DONE;
}
depth.resize(cnt_art_points + cnt_bicon + 1);
depth[gica_tree] = 1;
dfs_depth(gica_tree);
int nearest_node = santa_tree;
for(int u: tree_path)
if(depth[nearest_node] > depth[u])
nearest_node = u;
// first node in the list was an articulation point
if(tree_path[0] > cnt_bicon) pop_first(tree_path);
// the last node in the list was an articulation point
if(tree_path.back() > cnt_bicon) tree_path.pop_back();
if(nearest_node != tree_path[0] && nearest_node != tree_path.back())
return IMPOSSIBLE;
// the path array is reversed from when it has been built
if(tree_path.back() == nearest_node) reverse(tree_path);
return append_shortest_path(tree_path[0]);
}
void output_imp(){
ofstream fout("santa.out");
fout << "No chance";
fout.close();
}
void output_final_path(){
ofstream fout("santa.out");
fout << final_path.size() << '\n';
for(int x: final_path)
fout << x << ' ';
fout.close();
}
int len, ending, hem_chain[SIGMA];
int generated_chain[SIGMA];
bool found_chain;
void back_tr(int k){
if(k == len){
if(ending == -1 || hem_chain[len - 1] == ending){
found_chain = 1;
for(int i = 0; i < len; i++)
generated_chain[i] = hem_chain[i];
}
return;
}
for(int v: G[hem_chain[k - 1]]){
if(found_chain || !allowed[v] || seen[v]) continue;
hem_chain[k] = v;
seen[v] = 1;
back_tr(k + 1);
seen[v] = 0;
}
}
bool append_hem_cycle(int bc, int start, int end){
len = comp_bicon[bc].size(); ending = end;
for(int u: comp_bicon[bc]) allowed[u] = 1;
hem_chain[0] = start;
seen[start] = 1;
found_chain = 0;
back_tr(1);
for(int u: comp_bicon[bc]) allowed[u] = 0;
if(found_chain == 0) return 0;
for(int i = 1; i < len; i++) // ignore the first one cuz it would be added twice
final_path.push_back(generated_chain[i]);
return 1;
}
int main(){
read_graph();
compute_tree_bicon();
int head = first_test();
if(head == IMPOSSIBLE){
output_imp();
return 0;
}
if(head == ALR_DONE){
output_final_path();
return 0;
}
bool still_possible = 1;
seen.reset();
for(int i = 0; i < (int)tree_path.size() && still_possible; i++){
if(tree_path[i] > cnt_bicon) continue;
int tail = (i + 1 < (int)tree_path.size()?
node_to_art[tree_path[i + 1] - cnt_bicon]:
-1
);
if(!append_hem_cycle(tree_path[i], head, tail))
still_possible = 0;
head = tail;
}
if(still_possible)
output_final_path();
else
output_imp();
return 0;
}