Cod sursa(job #789157)

Utilizator mihai995mihai995 mihai995 Data 17 septembrie 2012 13:50:16
Problema Santa Scor 0
Compilator cpp Status done
Runda Lista lui wefgef Marime 4.54 kb
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stack>
#include <vector>
using namespace std;

const int N = 45005;
const char fail[] = "impossibru\n";

vector<int> graph[N], G[2 * N], comp[N], sol;
int T[2 * N], depth[N], componenta[N], n, S, D, Q, nrComp, nrU;

bool critic[N], use[N], STOP;
stack<int> lista;

struct Muchie{
	int x, y;

	Muchie(){
		x = y = 0;
	}

	Muchie(int _x, int _y){
		x = _x;
		y = _y;
	}
};

stack<Muchie> St;

ifstream in("santa.in");
ofstream out("santa.out");

void add(Muchie M, int C){
	int x = M.x, y = M.y;

	comp[C].push_back(x);
	comp[C].push_back(y);

	if (componenta[x] && componenta[x] != C)
		critic[x] = true;
	if (componenta[y] && componenta[y] != C)
		critic[y] = true;

	componenta[x] = C;
	componenta[y] = C;
}

void cbc(int x, int D, int T){
	depth[x] = D;

	St.push(Muchie(T, x));

	for (vector<int> :: iterator it = graph[x].begin() ; it != graph[x].end() ; it++){
		if (*it == T)
			continue;

		if (depth[*it]){
			if (!St.empty() && depth[*it] <= depth[St.top().x])
				++nrComp;

			while (!St.empty() && depth[*it] <= depth[St.top().x]){
				add(St.top(), nrComp);
				St.pop();
			}

			continue;
		}

		cbc(*it, 1 + D, x);
	}

	if (!St.empty() && St.top().x && St.top().y == x){
		add(St.top(), ++nrComp);
		St.pop();
	}
}

void cleanup(vector<int>& v){
	sort(v.begin(), v.end());

	int i, j;

	for (i = 0, j = 0 ; i < v.size() ; i++)
		if (v[i] != v[i - 1])
			v[j++] = v[i];

	v.resize(j);
}

void read(){
	int m, x, y;

	in >> n >> m;

	while (m--){
		in >> x >> y;

		graph[x].push_back(y);
		graph[y].push_back(x);
	}

	in >> S >> D >> Q;
}

void add_edge(int x, int y){
	G[x].push_back(y);
	G[y].push_back(x);
}

void arbore(){
	for (int k = 1 ; k <= nrComp ; k++)
		for (vector<int> :: iterator it = comp[k].begin() ; it != comp[k].end() ; it++)
			if (critic[*it])
				add_edge(N + k, *it);
}

void dfs(int x){
	for (vector<int> :: iterator it = G[x].begin() ; it != G[x].end() ; it++)
		if (!T[*it]){
			T[*it] = x;
			dfs(*it);
		}
}

bool same_comp(int x, int y){
	if (x == y)
		return true;

	for (int i = 1 ; i <= nrComp ; i++){
		int nr = 0;

		for (vector<int> :: iterator it = comp[i].begin() ; it != comp[i].end() ; it++)
			if (*it == x || *it == y)
				++nr;

		if (nr > 1)
			return true;
	}

	return false;
}

void sch(int& a, int& b){
	int c = a;
	a = b;
	b = c;
}

void bkt(vector<int>& v, int x, int D){
	if (STOP)
		return;

	--nrU;
	sol.push_back(x);
	use[x] = true;

	if (x == D){
		STOP = nrU == 0;
		return;
	}

	if (D == -1 && !nrU){
		STOP = true;
		return;
	}



	for (vector<int> :: iterator it = graph[x].begin() ; it != graph[x].end() ; it++)
		if (!use[*it]){
			use[*it] = true;
			bkt(v, *it, D);
		}

	if (!STOP)
		sol.pop_back();

	use[x] = false;
	++nrU;
}

bool solvable(vector<int>& v, int S, int D){
	memset(use, true, sizeof(use));

	for (vector<int> :: iterator it = v.begin() ; it != v.end() ; it++)
		use[*it] = false;

	STOP = false;

	nrU = v.size();

	bkt(v, S, D);

	return STOP;
}

bool solve(){
	int S, D, C;

	while (!lista.empty()){
		S = lista.top(); lista.pop();
		C = lista.top();lista.pop();
		D = -1;

		if (!lista.empty())
			D = lista.top();

		if (!solvable(comp[C - N], S, D))
			return false;
	}

	return true;
}

int main(){
	read();

	//componente biconexe

	cbc(S, 0, 0);

	for (int i = 1 ; i <= nrComp ; i++)
		cleanup(comp[i]);
/*
	cout << nrComp << "\n";

	for (int i = 1 ; i <= nrComp ; i++){
		for (vector<int> :: iterator it = comp[i].begin() ; it != comp[i].end() ; it++)
			cout << *it << " ";
		cout << "\n";
	}

	for (int i = 1 ; i <= n ; i++)
		cout << critic[i] << " ";

	cout << "\n";
*/
	arbore(); //construire arbore cbc

	//determinare drum
	if (!same_comp(S, Q) && !same_comp(D, Q)){
		out << fail;
		return 0;
	}

	if (!same_comp(S, Q))
		sch(S, D);

	S = critic[S] ? S : componenta[S] + N;
	D = critic[D] ? D : componenta[D] + N;

	T[S] = -1;
	dfs(S);

	if (D < N)
		D = T[D];

	for (int i = D ; i > 0 ; i = T[i])
		lista.push(i);

	if (lista.top() < N)
		lista.pop();

	lista.push(Q);
/*
	while (!lista.empty()){
		cout << lista.top() << " ";
		lista.pop();
	}
*/
	if (!solve()){
		out << fail << "\n";
		return 0;
	}

	out << sol.size() << "\n";

	for (vector<int> :: iterator it = sol.begin() ; it != sol.end() ; it++)
		out << *it << " ";

	out << "\n";

	return 0;
}