Cod sursa(job #1098111)

Utilizator scipianusFMI Ciprian Olariu scipianus Data 4 februarie 2014 14:44:31
Problema Nowhere-zero Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.34 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#define pii pair<int, int>
using namespace std;
int n, m, P0, nreg, grad[300100], color[300100];
pii regiune[300100], M[300100];
double X[100100], Y[100100];
vector <pii> G[100100];
vector <int> GReg[300100], coloringorder;
vector <bool> viz[100100];
map <int, int> IndexMuchie[100100];
set <pii> Q;
bool sters[300100], uz[7];

inline void Citire()
{
	int i, x, y;
	ifstream fin("nowhere-zero.in");
	fin >> n >> m;
	for(i = 1; i <= n; ++i)
		fin >> X[i] >> Y[i];
	for(i = 1; i <= m; ++i)
	{
		fin >> x >> y;
		G[x].push_back(make_pair(y, i));
		G[y].push_back(make_pair(x, i));
	}
	fin.close();
}

inline bool Sortare(pii a, pii b)
{
	return atan2(Y[a.first] - Y[P0], X[a.first] - X[P0]) < atan2(Y[b.first] - Y[P0], X[b.first] - X[P0]);
}

inline void BuildRegionGraph()
{
	int i, j, A, B, nod, poz, nextnod, muchie;
	for(i = 1; i <= n; ++i)
	{
		// sortez vecinii punctului in jurul lui
		P0 = i;
		sort(G[i].begin(), G[i].end(), Sortare);
		grad[i] = G[i].size();
		viz[i].reserve(grad[i]);
		for(j = 0; j < grad[i]; ++j)
			IndexMuchie[i][G[i][j].first] = j;
	}
	for(i = 1; i <= n; ++i)
	{
		for(j = 0; j < grad[i]; ++j)
		{
			if(!viz[i][j])
			{
				nreg++; // am o regiune noua
				nod = i;
				poz = j;
				do // construiesc regiunea, parcurgand muchiile ce o inconjoara
				{
					viz[nod][poz] = true;
					nextnod = G[nod][poz].first;
					muchie = G[nod][poz].second;
					if(regiune[muchie].first == 0)
					{
						regiune[muchie].first = nreg;
						M[muchie] = make_pair(nod, nextnod);
					}
					else
						regiune[muchie].second = nreg;
					poz = IndexMuchie[nextnod][nod] + 1;
					if(poz == grad[nextnod])
						poz = 0;
					nod = nextnod;
				}
				while(nod != i);
			}
		}
	}
	// construiesc graful regiunilor
	for(i = 1; i <= m; ++i)
	{
		A = regiune[i].first;
		B = regiune[i].second;
		// regiunile A, B se ating in muchia i
		GReg[A].push_back(B);
		GReg[B].push_back(A);
	}
}

inline void ColoreazaGrafRegiuni()
{
	vector <int>::iterator it;
	pii now;
	int i, x, c;
	for(i = 1; i <= nreg; ++i)
	{
		grad[i] = GReg[i].size();
		Q.insert(make_pair(grad[i], i));
	}
	while(!Q.empty())
	{
		now = *Q.begin();
		Q.erase(now);
		x = now.second;
		if(sters[x])
			continue;
		sters[x] = true;
		coloringorder.push_back(x);
		for(it = GReg[x].begin(); it != GReg[x].end(); ++it)
		{
			if(!sters[*it])
			{
				Q.erase(make_pair(grad[*it], *it));
				grad[*it]--;
				Q.insert(make_pair(grad[*it], *it));
			}
		}
	}
	for(i = nreg - 1; i >= 0; --i)
	{
		x = coloringorder[i];
		for(c = 1; c <= 6; ++c)
			uz[c] = false;
		for(it = GReg[x].begin(); it != GReg[x].end(); ++it)
			uz[color[*it]] = true;
		c = 1;
		while(uz[c])
			c++;
		color[x] = c;
	}
}

inline void Afisare()
{
	int i, x, y, capacitate;
	ofstream fout("nowhere-zero.out");
	for(i = 1; i <= m; ++i)
	{
		x = M[i].first;
		y = M[i].second;
		capacitate = color[regiune[i].first] - color[regiune[i].second];
		if(capacitate > 0)
			fout << x << ' ' << y << ' ' << capacitate << "\n";
		else
			fout << y << ' ' << x << ' ' << (-capacitate) << "\n";
	}
	fout.close();
}

int main()
{
	Citire();
	BuildRegionGraph();
	ColoreazaGrafRegiuni();
	Afisare();
	return 0;
}