Cod sursa(job #783576)

Utilizator mihaipopa12Popa Mihai mihaipopa12 Data 3 septembrie 2012 12:56:50
Problema Santa Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.98 kb
#include<stdio.h>
#include<vector>
#include<stack>
#include<algorithm>
#include<cstdlib>

#define maxn 45005
#define pb push_back
#define mp make_pair

using namespace std;

FILE*f=fopen("santa.in","r");
FILE*g=fopen("santa.out","w");

int n,m,S,E,Q,S2,E2,Q2,last,c,found,faraprimul;
int viz[maxn],niv[maxn],lowest[maxn],critic[maxn],comp[maxn],niv_arb[maxn<<1],T[maxn<<1],used[maxn],x[maxn],p,care_critic[maxn];
int critice;
vector<int>G[maxn],v,W[maxn<<1],left,right,sol;
vector< vector<int> >C;
stack< pair<int,int> >st;

inline void componenta ( int x , int y ){
	int nod1,nod2;
	
	do{
		nod1 = st.top().first; nod2 = st.top().second;
		st.pop();
		v.pb(nod1); v.pb(nod2); comp[nod1] = comp[nod2] = C.size();
	}while(nod1 != x || nod2 != y );
	
	sort(v.begin(),v.end());
	vector<int>::iterator itt = unique(v.begin(),v.end());
	v.resize(itt-v.begin());
	
	C.pb(v);
	v.clear();
}

void dfs ( int nod , int t ){
	viz[nod] = 1;
	niv[nod] = lowest[nod] = niv[t]+1;
	
	for ( vector<int>::iterator itt = G[nod].begin() ; itt != G[nod].end() ; ++itt ){
		int nodvcn = (*itt);
		if ( nodvcn == t )	continue ;
		
		if ( !viz[nodvcn] ){
			st.push(mp(nod,nodvcn));
			dfs(nodvcn,nod);
			
			// TODO(mihai): Te-ai intors din recursivitate, updateaza dinamica lowest cu valoarea din fiu
			if ( lowest[nodvcn] < lowest[nod] ){
				lowest[nod] = lowest[nodvcn];
			}
			
			if ( lowest[nodvcn] >= niv[nod] ){
				if ( nod - 1 ){
					critic[nod] = ++critice;
					care_critic[critice] = nod;
				}
				componenta(nod,nodvcn);
			}
		} else {
			// TODO(mihai): Trateaza cazul cand ai o muchie de intoarcere, updateaza dinamica lowest
			lowest[nod] = min(lowest[nod],niv[nodvcn]);
		}
	}
}

inline void biconex () {
	
	for ( int i = 1 ; i <= n ; ++i ){
		if ( !viz[i] ){
			dfs(i,0);
		}
	}
}

inline void nochance () {
	
	fprintf(g,"No chance\n");
	fclose(f); fclose(g);
	exit(0);
}

inline void graf () {
	
	for ( int i = 0 ; i < C.size() ; ++i ){
		
		for ( vector<int>::iterator itt = C[i].begin() ; itt != C[i].end() ; ++itt ){
			int nod = (*itt);
			if ( critic[nod] ){
				W[i+1].pb(C.size()+critic[nod]);
				W[C.size()+critic[nod]].pb(i+1);
			}
		}
	}
}

inline void coresp ( int x , int &x2 ){
	
	if ( critic[x] ){
		x2 = C.size() + critic[x];
	}
	else{
		x2 = comp[x]+1;
	}
}

void dfs_arbore ( int nod , int t ){
	niv_arb[nod] = niv_arb[t] + 1;
	
	for ( vector<int>::iterator itt = W[nod].begin() ; itt != W[nod].end() ; ++itt ){
		int nodvcn = (*itt);
		if ( nodvcn == t )	continue ;
		
		T[nodvcn] = nod;
		dfs_arbore(nodvcn,nod);
	}
}

inline void find_passed () {
	
	coresp(S,S2);
	coresp(E,E2);
	coresp(Q,Q2);
	
	dfs_arbore(1,0);
	
	while ( S2 != E2 ){
		
		if ( niv_arb[S2] >= niv_arb[E2] ){
			left.pb(S2);
			S2 = T[S2];
		}
		else{
			right.pb(E2);
			E2 = T[E2];
		}
	}
	left.pb(S2);
	reverse(right.begin(),right.end());
	for ( vector<int>::iterator itt = right.begin() ; itt != right.end() ; ++itt ){
		left.pb(*itt);
	}
}

void back ( int nod ){
	used[nod] = 1; x[++p] = nod;
	
	if ( p == C[c].size() ){
		if ( nod == last || last == -1 ){
			found = 1;
			for ( int i = 1 + faraprimul ; i <= p ; ++i ){
				sol.pb(x[i]);
			}
		}
		return ;
	}
	
	for ( vector<int>::iterator itt = G[nod].begin() ; itt != G[nod].end() && !found ; ++itt ){
		int nodvcn = (*itt);
		
		if ( !used[nodvcn] && comp[nodvcn] == c ){
			back(nodvcn);
		}
	}
	
	used[nod] = 0;
	x[p--] = 0;
}

inline void find_tour () {
	
	if ( left[left.size()-1] > C.size() ){
		if ( Q2 == left[left.size()-1] ){
			Q2 = left[left.size()-2];
			left.pop_back();
			reverse(left.begin(),left.end());
		}
		else{
			left.pop_back();
		}
	}
	if ( left[0] > C.size() ){
		if ( Q2 == left[0] ){
			Q2 = left[1];
		}
		reverse(left.begin(),left.end());
		left.pop_back();
		reverse(left.begin(),left.end());
	}
	
	if ( Q2 != left[0] && Q2 != left[left.size()-1] ){
		nochance();
	}
	
	int i,start = Q;
	i = 0;
	
	for ( ; i < left.size() ; i += 2 ){
		c = left[i]-1;
		for ( vector<int>::iterator itt = C[c].begin() ; itt != C[c].end() ; ++itt ){
			comp[*itt] = c;
		}
		
		found = 0;
		if ( i < left.size() - 1 )
			last = care_critic[left[i+1] - C.size()];
		else
			last = -1;
		
		p = 0; back(start);
		faraprimul = 1;
		start = last;
		
		if ( !found ){
			nochance();
		}
	}
	
	fprintf(g,"%d\n",sol.size());
	for ( vector<int>::iterator itt = sol.begin() ; itt != sol.end() ; ++itt ){
		fprintf(g,"%d ",*itt);
	}
	fprintf(g,"\n");
}

inline void show ( vector<int>A ){
	for ( vector<int>::iterator itt = A.begin() ; itt != A.end() ; ++itt ){
		printf("%d ",*itt);
	}
	printf("\n");
}

int main () {
	
	fscanf(f,"%d %d",&n,&m);
	int x,y;
	for ( int i = 1 ; i <= m ; ++i ){
		fscanf(f,"%d %d",&x,&y);
		G[x].pb(y);
		G[y].pb(x);
	}
	fscanf(f,"%d %d %d",&S,&E,&Q);
	
	biconex();
	graf();
	
	find_passed();
	
	find_tour();
	
	fclose(f);
	fclose(g);
	
	return 0;
}