/**
 * O(V + Vlog(V) + Elog(V))
 * @param G [description]
 * @param s [description]
 */
void MST_prim(IGraph &G, IGraph::vertex &s, double inf = 1e100){
	int n = G.numVertices();
	bool *isQ = new bool[n];
	IGraph::vertex ** pi = new IGraph::vertex *[n];

	typedef pair<double, int> vi;
	
 	vector<vi> vertices;

 	IndexedPriorityQueue<double, less<double> > Q(n);

	for (int i = 0; i < n; ++i)
	{
		vertices.push_back(make_pair(inf, i));
		Q.insert(i, inf);
		pi[i] = NULL;
		isQ[i] = true;
	}

	vertices[s.id].first = 0;
	Q.changeKey(s.id, 0);

	int it = 0;
	while(!Q.isEmpty()){

		int id = Q.minIndex(); // O(1)
		Q.deleteMin(); // O(lg(v))

		cout << id << endl;

		isQ[id] = false;
		IGraph::vertex *u = G.getVertex(id);
		for (IGraph::vertex::iterator v = u->begin(); v != u->end(); ++v)
		{
			double w = G.getEdge(id, v->second->id);
			if(isQ[v->second->id] &&  w < vertices[v->second->id].first){// O(1)
				pi[v->second->id] = u;
				Q.changeKey(v->second->id, w); // O(log(v))
				vertices[v->second->id].first = w;
			}
		}

	}

	cout << "PRIMs : ";
	for (int i = 0; i < n; ++i)
	{
		if(pi[i] != NULL)
			cout << pi[i]->id << " ";
		else
			cout << "nil ";
	}
	cout << endl;

	delete [] isQ;

}
/**
 * O(V + E)
 * @param G  Graph
 * @param s source vertex
 */
void BFS(IGraph &G, IGraph::vertex &s){
	
	int n = G.numVertices();
	int *color = new int[n];
	int *d = new int[n];
	IGraph::vertex **pi = new IGraph::vertex*[n];
	
	for (IGraph::vertex_iterator v = G.begin(); v != G.end(); ++v)
	{
		color[v->id] = WHITE;
		pi[v->id] = NULL;
		d[v->id] = 1000000;
	}

	color[s.id] = GRAY;
	d[s.id] = 0;

	queue<IGraph::vertex * > Q;
	Q.push(&s); 
	while(!Q.empty()){

		IGraph::vertex * u = Q.front();
		for (IGraph::vertex::iterator e = u->begin(); e != u->end(); e++)
		{
			IGraph::vertex * v = e->second;	
			if(color[v->id] == WHITE){
				color[v->id] = GRAY;
				d[v->id] = d[u->id] + 1;
				pi[v->id] = u;
				Q.push(&(*v)); 
			}
		}
		color[u->id] = BLACK;
		Q.pop();
	}

	cout << "S : " << s.id << endl;
	for (int i = 0; i < n; ++i)
	{
		if(pi[i] != NULL)
			cout << pi[i]->id << " ";
		else
			cout << "nil ";
	}
	cout << endl;

	delete [] color;
	delete [] d;
	delete [] pi;
}
/**
 * complexity : O(V + E)
 * @param G Graph
 * @param s source vertex
 */
void DFS(IGraph &G, IGraph::vertex &s){

	int n = G.numVertices();
	int *color = new int[n];
	int *d = new int[n];
	int *f = new int[n];
	IGraph::vertex **pi = new IGraph::vertex*[n];
	
	for (IGraph::vertex_iterator v = G.begin(); v != G.end(); ++v)
	{
		color[v->id] = WHITE;
		pi[v->id] = NULL;
		d[v->id] = 0;
		f[v->id] = 0;
	}

	int dtime = 0;

	DFS_visit(G, s, color, d, f, pi, dtime);
	for (IGraph::vertex_iterator v = G.begin(); v != G.end(); ++v)
	{
		if(color[v->id] == WHITE){
			DFS_visit(G, *v, color, d, f, pi, dtime);
		}
	}

	cout << "S : " << s.id << endl;
	for (int i = 0; i < n; ++i)
	{
		if(pi[i] != NULL)
			cout << pi[i]->id << "(" << d[i] << "/" << f[i] <<  ") ";
		else
			cout << "nil" << "(" << d[i] << "/" << f[i] <<  ") ";
	}
	cout << endl;

	delete [] color;
	delete [] d;
	delete [] f;
	delete [] pi;
}
void DVhamiltonPathForTournament(IGraph &tour, int * path){
	int * buffer = new int[tour.numVertices()];

	tour_ham_sort_and_count(tour, path, buffer, 0, tour.numVertices() - 1);
}