Cod sursa(job #22728)

Utilizator gcosminGheorghe Cosmin gcosmin Data 27 februarie 2007 10:47:09
Problema Santa Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.96 kb
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <bitset>
using namespace std;

#define NMAX 45010
#define MP make_pair

int N, M, S, E, Q;

int nleg[NMAX];
vector <int> leg[NMAX];

int niv[NMAX];
int niv_up[NMAX];
int tata[NMAX];
int nmm = 0;
pair <int, int> mm[NMAX];

int ncomp = 0;
vector <int> comp[NMAX];
int comp_size[NMAX];
vector <int> legc[NMAX][16];
vector <int> ap_comp[NMAX];

vector <int> legt[NMAX + NMAX];

int nrpa;
char is_pa[NMAX];

inline int MIN(int a, int b) { return (a < b) ? a : b; }

void bf(int x)
{
	niv[x] = niv[tata[x]] + 1;
	niv_up[x] = niv[x];

	int aux;

	for (vector <int> :: iterator it = leg[x].begin(); it != leg[x].end(); ++it)
		if (!niv[*it]) {
			mm[++nmm] = MP(x, *it);
			aux = nmm;
			tata[*it] = x;
			bf(*it);
			niv_up[x] = MIN(niv_up[x], niv_up[*it]);

			if (niv_up[*it] >= niv[x]) {
				is_pa[x] = 1;
				ncomp++;
				ap_comp[x].push_back(ncomp);
				while (nmm >= aux) {
					comp[ncomp].push_back(mm[nmm].second);
					ap_comp[mm[nmm--].second].push_back(ncomp);
				}
				comp[ncomp].push_back(x);
				sort(comp[ncomp].begin(), comp[ncomp].end());
				comp_size[ncomp] = comp[ncomp].size();
			}
		} else if (*it != tata[x]) niv_up[x] = MIN(niv_up[x], niv[*it]);
}

int search_leg(int xx, int yy)
{
	int step = nleg[xx], x = 0, n = nleg[xx], q;

	while ((q = (step & (step - 1)))) step = q;

	for (; step; step >>= 1)
		if (x + step < n && leg[xx][x + step] <= yy)
			x += step;

	if (leg[xx][x] == yy) return 1;

return 0;
}

int search_comp(int x)
{
	if (is_pa[x]) return ncomp + x;

	int i, j;

	for (i = 1; i <= ncomp; i++)
		for (j = 0; j < comp_size[i]; j++)
			if (x == comp[i][j]) return i;

return -1; // nu ar trebui sa ajung aici
}

int pred[NMAX + NMAX];
char viz[NMAX + NMAX];

void df(int x)
{
	viz[x] = 1;

	for (vector <int> :: iterator it = legt[x].begin(); it != legt[x].end(); ++it)
		if (!viz[*it]) {
			pred[*it] = x;
			df(*it);
		}
}

int cd[NMAX];

int drum[50];

int rez[NMAX];

bitset <1 << 16> stare[16];

int back(int x, int y, int mask, int end, int e, int comp)
{
	if (stare[mask][x]) return 0;
	stare[mask][x] = 1;
	
	if (mask == end) {
		if (e) {
			if (x == y) return 1;
			return 0;
		}
		return 1;
	}

	for (vector <int> :: iterator it = legc[comp][x].begin(); it != legc[comp][x].end(); ++it)
		if (!(mask & (1 << (*it)))) {
			drum[++drum[0]] = *it;
			if (back(*it, y, mask | (1 << *it), end, e, comp)) return 1;
			drum[0]--;
		}
return 0;
}
	
int main()
{
	int i, x, y, j, jj;
	
	freopen("santa.in", "r", stdin);
	freopen("santa.out", "w", stdout);
	
	scanf("%d %d", &N, &M);

	for (i = 1; i <= M; i++) {
		scanf("%d %d", &x, &y);

		leg[x].push_back(y);
		leg[y].push_back(x);
		nleg[x]++, nleg[y]++;
	}

	scanf("%d %d %d", &S, &E, &Q);

	for (i = 1; i <= N; i++) sort(leg[i].begin(), leg[i].end());

	bf(1);

	int nr = 0;
	is_pa[1] = 0;
	for (i = 1; i <= N; i++) if (tata[i] == 1) nr++;
	if (nr > 1) is_pa[1] = 1;

	for (i = 1; i <= N; i++) {
		if (!is_pa[i]) continue;
		nrpa++;		

		for (vector <int> :: iterator it = ap_comp[i].begin(); it != ap_comp[i].end(); ++it) {
			legt[ncomp + i].push_back(*it);
			legt[*it].push_back(ncomp + i);
		}
	}

	for (i = 1; i <= ncomp; i++) {
		for (j = 0; j < comp_size[i]; j++)
			for (jj = 0; jj < comp_size[i]; jj++)
				if (search_leg( comp[i][j], comp[i][jj] ))
					legc[i][j].push_back(jj);
	}

	int beg = search_comp(S);
	int end = search_comp(E);
	df(beg);

	int cur = end;

	while (cur != beg) {
		if (cur <= ncomp) cd[++cd[0]] = cur;
		cur = pred[cur];
	}
	if (cur <= ncomp) cd[++cd[0]] = cur;

	int cmax = -1;

	int cc = cd[1];

	for (j = 0; j < comp_size[cc]; j++) if (comp[cc][j] == Q) break;
	if (j < comp_size[cc]) cmax = cc;
	else {
		cc = cd[cd[0]];

		for (j = 0; j < comp_size[cc]; j++) if (comp[cc][j] == Q) break;
		if (j < comp_size[cc]) cmax = cc;
	}

	if (cmax == -1) {
		printf("NU\n");
		return 0;
	}

	int bg, en, ps, cu, urm = 0, pc = 0, pu = 0;

	if (cmax == cd[1]) bg = 1, en = cd[0], ps = 1;
	else bg = cd[0], en = 1, ps = -1;

	cur = Q;

	E = 1;
	rez[++rez[0]] = cur;
	for (i = bg; i != en; i += ps) {
		cc = cd[i];
		cu = cd[i + ps];

		for (j = 0; j < comp_size[cc]; j++) {
			if (comp[cc][j] == cur) pc = j;
			for (jj = 0; jj < comp_size[cu]; jj++)
				if (comp[cc][j] == comp[cu][jj]) urm = comp[cc][j], pu = j;
		}

		drum[0] = 0;
		for (j = 0; j < 16; j++) stare[j] = 0;
		back(pc, pu, 1 << pc, (1 << comp_size[cc]) - 1, 1, cc);

		if (drum[0] != comp_size[cc] - 1) E = 0;

		for (j = 1; j <= drum[0]; j++) rez[++rez[0]] = comp[cc][drum[j]]; //printf("%d ", comp[cc][drum[j]]);

		cur = urm;
	}

	cc = cd[i];


	for (j = 0; j < comp_size[cc]; j++)
		if (comp[cc][j] == cur) pc = j;

	drum[0] = 0;
	for (j = 0; j < 16; j++) stare[j] = 0;
	back(pc, pu, 1 << pc, (1 << comp_size[cc]) - 1, 0, cc);

	for (j = 1; j <= drum[0]; j++) rez[++rez[0]] = comp[cc][drum[j]]; //printf("%d ", comp[cc][drum[j]]);

	if (!E) {
		printf("NU\n");
		return 0;
	}

	printf("%d\n", rez[0]);

	for (i = 1; i <= rez[0]; i++) printf("%d ", rez[i]);
	printf("\n");
		
fclose(stdin);
fclose(stdout);
return 0;
}