Cod sursa(job #1928989)

Utilizator iordache.bogdanIordache Ioan-Bogdan iordache.bogdan Data 16 martie 2017 22:23:29
Problema Nowhere-zero Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.15 kb
#include <fstream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <set>
#include <bitset>
#include <queue>

const int kMaxVertices = 100010;
const int kMaxEdges = 600010;
const int kMaxFaces = 300010;

struct Point {
	Point (double _x = 0, double _y = 0) :
		x(_x),
		y(_y) {
	}

	double x, y;
};

struct Edge {
	Edge (int _first = 0, int _second = 0, int _nextOnFace = 0, int _face = 0) :
		first(_first),
		second(_second),
		nextOnFace(_nextOnFace),
		face(_face) {
	}

	int first, second;
	int nextOnFace, face;
};

int vertexCount;
Point vertices[kMaxVertices];

int edgeCount;
Edge edges[kMaxEdges];

std::vector< int > adjEdges[kMaxVertices];

int faceCount;
std::vector< int > faceGraph[kMaxFaces];
std::set< std::pair<int, int> > faceEdges;
int faceGraphDegrees[kMaxFaces], color[kMaxFaces];

inline int RevEdge(const int& edge) {
	return (edge ^ 1);
}

inline void ComputeNextOnFaceForAllEdges() {
	for (int i = 1; i <= vertexCount; ++i) {
		Point& vertex = vertices[i];

		std::sort(adjEdges[i].begin(), adjEdges[i].end(),
		[&](const int& a, const int& b) {
			Point& first = vertices[edges[a].second];
			Point& second = vertices[edges[b].second];

			return atan2(first.y - vertex.y, first.x - vertex.x)
					< atan2(second.y - vertex.y, second.x - vertex.x);
		});

		for (int curr = 0; curr < (int)adjEdges[i].size(); ++curr) {
			int next = curr + 1;
			if (next == (int)adjEdges[i].size())
				next = 0;

			edges[RevEdge(adjEdges[i][next])].nextOnFace = adjEdges[i][curr];
		}
	}
}

inline void ComputeFaces() {
	for (int i = 0; i < edgeCount; ++i) {
		if (edges[i].face != 0)
			continue;

		edges[i].face = ++faceCount;
		for (int edge = edges[i].nextOnFace; edge != i; edge = edges[edge].nextOnFace)
			edges[edge].face = faceCount;
	}
}

inline void ComputeFaceGraph() {
	for (int i = 0; i < edgeCount; i += 2) {
		int first = edges[i].face;
		int second = edges[i + 1].face;

		faceEdges.insert(std::make_pair( std::min(first, second), std::max(first, second) ));
	}

	for (std::pair<int, int> edge : faceEdges) {
		faceGraph[edge.first].push_back(edge.second);
		faceGraphDegrees[edge.first]++;

		faceGraph[edge.second].push_back(edge.first);
		faceGraphDegrees[edge.second]++;
	}
}

inline void ColorFaceGraph() {
	std::queue< int > que;
	std::vector< int > orderedFaces;

	for (int i = 1; i <= faceCount; ++i) {
		if (faceGraphDegrees[i] > 5)
			continue;

		que.push(i);
		orderedFaces.push_back(i);
	}

	while (!que.empty()) {
		int face = que.front();
		que.pop();

		for (int adj : faceGraph[face]) {
			faceGraphDegrees[adj]--;

			if (faceGraphDegrees[adj] == 5) {
				que.push(adj);
				orderedFaces.push_back(adj);
			}
		}
	}

	std::reverse(orderedFaces.begin(), orderedFaces.end());

	std::bitset< kMaxFaces > fixed; fixed.reset();
	std::bitset< 10 > appeared;

	for (int face : orderedFaces) {
		fixed[face] = true;

		appeared.reset();
		for (int adj : faceGraph[face])
			if (fixed[adj])
				appeared[ color[adj] ] = true;

		for (int i = 1; i <= 6; ++i) {
			if (appeared[i])
				continue;

			color[face] = i;
			break;
		}
	}
}

int main() {
	std::ifstream inputFile("nowhere-zero.in");
	std::ofstream outputFile("nowhere-zero.out");

	inputFile >> vertexCount >> edgeCount;

	for (int i = 1; i <= vertexCount; ++i)
		inputFile >> vertices[i].x >> vertices[i].y;

	int cnt = 0;
	for (int i = 1; i <= edgeCount; ++i) {
		int first, second;
		inputFile >> first >> second;

		edges[cnt++] = Edge(first, second);
		adjEdges[first].push_back(cnt - 1);

		edges[cnt++] = Edge(second, first);
		adjEdges[second].push_back(cnt - 1);
	}
	edgeCount = cnt;

	ComputeNextOnFaceForAllEdges();
	ComputeFaces();
	ComputeFaceGraph();
	ColorFaceGraph();

	for (int i = 0; i < edgeCount; ++i) {
		int first = edges[i].face;
		int second = edges[RevEdge(i)].face;

		if (color[first] < color[second])
			continue;

		outputFile << edges[i].first << ' ' << edges[i].second << ' ' << color[first] - color[second] << '\n';
	}

	inputFile.close();
	outputFile.close();

	return 0;
}

//Trust me, I'm the Doctor!