Cod sursa(job #155)

Utilizator wefgefAndrei Grigorean wefgef Data 5 decembrie 2006 22:16:30
Problema Santa Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.89 kb
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string.h>

using namespace std;

#define Nmax 45005
#define Mmax 130005
#define sz(a) (a.size())

vector< vector<int> > vec, comp, nod, vcomp;
vector<int> aux, aux2, drum, rez;

int n, f1, f2, f3;
int viz[Nmax], par[Nmax], niv[Nmax], nivmax[Nmax], cont, m1[Mmax], m2[Mmax], nrc, viz2[Nmax];
char mf1[Nmax], mf2[Nmax], mf3[Nmax], nosol, ad[16][16];
int Q[Mmax], ppar[Mmax], elpar[Mmax], ord[Nmax], timp[Nmax];
int c[16][1<<16], cnt, Qi[16*(1<<16)], Qj[16*(1<<16)], Qp[16*(1<<16)];

void readdata()
{
	freopen("santa.in", "r", stdin);
	freopen("santa.out", "w", stdout);
	
	int i, m, a, b;
	
	scanf("%d %d", &n, &m);
	vec.resize(n+1);
	for (i = 1; i <= m; ++i)
	{
		scanf("%d %d", &a, &b);
		vec[a].push_back(b);
		vec[b].push_back(a);
	}
	scanf("%d %d %d", &f1, &f2, &f3);
}

//componente biconexe
void insert(int x, int y)
{
	m1[++cont] = x;
	m2[cont] = y;
}

void scoate(int x, int y)
{
	int i;
	
	aux.clear();
	while (m1[cont] != x || m2[cont] != y)
	{
		aux.push_back(m1[cont]);
		aux.push_back(m2[cont--]);
	}
	aux.push_back(m1[cont]);
	aux.push_back(m2[cont--]);
	sort(aux.begin(), aux.end());
	
	aux2.clear();
	aux2.push_back(aux[0]);
	for (i = 1; i < sz(aux); ++i)
		if (aux[i] > aux[i-1])
			aux2.push_back(aux[i]);
					
	comp.push_back(aux2);
	for (i = 0; i < sz(aux2); ++i)
		nod[aux2[i]].push_back(nrc);
	nrc++;
}

void df(int k)
{
	int i, lim, nod;
	
	viz[k] = 1;
	nivmax[k] = niv[k];
	
	lim = sz(vec[k]);
	for (i = 0; i < lim; ++i)
	{
		nod = vec[k][i];
		if (!viz[nod])
		{
			par[nod] = k;
			niv[nod] = niv[k]+1;
			insert(k, nod);
			df(nod);
			if (nivmax[nod] < nivmax[k]) nivmax[k] = nivmax[nod];
			if (nivmax[nod] >= niv[k]) scoate(k, nod);
		}
		else
		if (nod != par[k] && niv[nod] < niv[k])
		{
			insert(k, nod);
			if (niv[nod] < nivmax[k])
				nivmax[k] = niv[nod];
		}
	}
}
//end of componente biconexe


void lee()
{
	int i, j, lim, start = -1, m1 = 0, m2 = 0, ind = 1, cur, val, nou;
	
	cont = 1;
	for (i = 0; i < nrc; ++i)
	{
		lim = sz(comp[i]);
		for (j = 0; j < lim; ++j)
		{
			if (comp[i][j] == f1) mf1[i] = 1;
			if (comp[i][j] == f2) mf2[i] = 1;
			if (comp[i][j] == f3) mf3[i] = 1;
		}
	}
	for (i = 0; i < nrc; ++i)
		if (mf1[i] && mf3[i] || mf2[i] && mf3[i])
		{ start = i; break; }
	if (start == -1) { nosol = 1; return; }
	
	//lee propriu-zis
	memset(viz, 0, sizeof(viz));
	Q[1] = start;
	elpar[1] = f3;
	viz2[start] = 1;
	
	if (mf1[start]) m1 = 1;
	if (mf2[start]) m2 = 1;

	while (!(m1 && m2))
	{
		cur = Q[ind];
		lim = comp[cur].size();
		for (i = 0; i < lim; ++i)
		if (!viz[comp[cur][i]])
		{
			val = comp[cur][i];
			viz[val] = 1;
			for (j = 0; j < sz(nod[val]); ++j)
				if (!viz2[nod[val][j]])
				{
					nou = nod[val][j];
					viz2[nou] = 1;
					Q[++cont] = nou;
					ppar[cont] = ind;
					elpar[cont] = val;
					if (mf1[nou]) m1 = 1;
					if (mf2[nou]) m2 = 1;
					if (m1 && m2) return;
				}
		}
		++ind;
	}
}

int found, e[16], nr, start1, stop1;
char eviz[16];

void back(int k)
{
	if (k == nr)
	{ found = 1; return; }
	for (int i = 0; i < nr; ++i)
	{
		if (!eviz[i] && ad[e[k-1]][i] )
		if ((i != start1) || (k == nr-1))
		{
			e[k] = i;
			eviz[i] = 1;
			back(k+1);
			eviz[i] = 0;
		}
		if (found) return;
	}
}

void dinamica(int start, int stop, int ind)
{
	int i, j, k, nod, nod2, el[16], lim, lim2, cap, cont;
	
	nr = sz(comp[ind]);
	
	//matrice de adiacenta
	memset(ad, 0, sizeof(ad));	
	lim = sz(comp[ind]);
	for (i = 0; i < lim; ++i)
	{
		ord[comp[ind][i]] = i;
		el[i] = comp[ind][i];
		timp[comp[ind][i]] = ind+1;
	}
	for (i = 0; i < lim; ++i)
	{
		nod = comp[ind][i];
		lim2 = sz(vec[nod]);
		for (j = 0; j < lim2; ++j)
		{
			nod2 = vec[nod][j];
			if (timp[nod2] == ind+1)
				ad[ord[nod]][ord[nod2]] = 1;
		}
	}
	
	//back de cacat, altceva mai inteligent nu intra in timp
	stop1 = ord[stop];
	if (start > -1) start1 = ord[start]; else start1 = -1;
	
	e[0] = stop1;
	found = 0;
	memset(eviz, 0, sizeof(eviz));
	eviz[stop1] = 1;
	back(1);

	for (i = nr-1; i >= 0; --i)
		drum.push_back(el[e[i]]);
}

int main()
{
	readdata();
	nod.resize(n+1);
	df(1);
	lee();
	
	if (nosol)
	{
		printf("No chance\n");
		return 0;
	}
	
	int last, pz, i;
	
	dinamica(-1, elpar[cont], Q[cont]);	
	if (nosol)
	{
		printf("No chance\n");
		return 0;
	}
	
    pz = ppar[cont]; last = elpar[cont];
	while (pz > 0)
	{
		dinamica(last, elpar[pz], Q[pz]);
		if (nosol)
		{
			printf("No chance\n");
			return 0;
		}		
		last = elpar[pz];
		pz = ppar[pz];
	}
	
	reverse(drum.begin(), drum.end());
	rez.push_back(drum[0]);
	for (i = 1; i < drum.size(); ++i)
		if (drum[i] != drum[i-1])
			rez.push_back(drum[i]);
			
	printf("%d\n", rez.size());			
	for (i = 0; i < rez.size(); ++i)
		printf("%d ", rez[i]);
	
	return 0;
}