Pagini recente » Cod sursa (job #3293833) | Cod sursa (job #3293575) | Istoria paginii preoni-2006/runda-4 | Cod sursa (job #3291211) | Cod sursa (job #968449)
Cod sursa(job #968449)
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
const int MAX_N = 100010;
const int MAX_M = 300010;
const int MAX_F = 200010;
const int NUM_COLORS = 6;
int n, m, num_faces;
pair<double, double> coord[MAX_N];
pair<int, int> edges[MAX_M], edge_faces[MAX_M];
vector<pair<int, int>> graph[MAX_N];
unordered_set<int> dual_graph[MAX_F];
unordered_map<int, int> index[MAX_N];
vector<bool> visited[MAX_N];
int deg[MAX_F], selected[MAX_N];
vector<int> coloring;
void ReadData() {
scanf("%d %d ", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf("%lf %lf ", &coord[i].first, &coord[i].second);
}
for (int i = 1; i <= m; ++i) {
int x, y;
scanf("%d %d ", &x, &y);
graph[x].push_back(make_pair(i, y));
graph[y].push_back(make_pair(i, x));
}
}
void ConstructDualGraph() {
for (int i = 1; i <= n; ++i) {
auto o = coord[i];
sort(graph[i].begin(), graph[i].end(),
[&o](const pair<int, int>& c1, const pair<int, int>& c2) {
int v1 = c1.second;
int v2 = c2.second;
return atan2(coord[v1].first - o.first, coord[v1].second - o.second) <
atan2(coord[v2].first - o.first, coord[v2].second - o.second);
});
}
for (int i = 1; i <= n; ++i) {
visited[i].resize(graph[i].size());
for (size_t j = 0; j < graph[i].size(); ++j) {
index[i][graph[i][j].second] = j;
}
}
for (int i = 1; i <= n; ++i) {
for (size_t j = 0; j < graph[i].size(); ++j) {
if (visited[i][j]) {
continue;
}
++num_faces;
int node = i, pos = j;
do {
visited[node][pos] = true;
int edge = graph[node][pos].first;
int next_node = graph[node][pos].second;
if (edge_faces[edge].first == 0) {
edge_faces[edge].first = num_faces;
edges[edge] = make_pair(node, next_node);
} else {
edge_faces[edge].second = num_faces;
}
pos = (index[next_node][node] + 1) % graph[next_node].size();
node = next_node;
} while (node != i);
}
}
for (int i = 1; i <= m; ++i) {
dual_graph[edge_faces[i].first].insert(edge_faces[i].second);
dual_graph[edge_faces[i].second].insert(edge_faces[i].first);
}
}
void FindDualGraphColoring() {
vector<int> ordering;
set<pair<int, int>> candidates;
for (int i = 1; i <= num_faces; ++i) {
deg[i] = dual_graph[i].size();
candidates.insert(make_pair(deg[i], i));
}
while (!candidates.empty()) {
int node = candidates.begin()->second;
candidates.erase(candidates.begin());
if (selected[node]) {
continue;
}
selected[node] = true;
ordering.push_back(node);
for (int v: dual_graph[node]) {
if (!selected[v]) {
candidates.insert(make_pair(--deg[v], v));
}
}
}
reverse(ordering.begin(), ordering.end());
coloring.resize(num_faces + 1);
vector<int> used_colors(NUM_COLORS + 1);
for (int node: ordering) {
for (int v: dual_graph[node]) {
used_colors[coloring[v]] = node;
}
bool found_color = false;
for (int i = 1; i <= NUM_COLORS; ++i) {
if (used_colors[i] != node) {
coloring[node] = i;
found_color = true;
break;
}
}
assert(found_color);
}
}
void PrintSolution() {
for (int i = 1; i <= m; ++i) {
int diff = coloring[edge_faces[i].first] - coloring[edge_faces[i].second];
if (diff < 0) {
printf("%d %d %d\n", edges[i].first, edges[i].second, -diff);
} else {
printf("%d %d %d\n", edges[i].second, edges[i].first, diff);
}
}
}
int main() {
freopen("nowhere-zero.in", "r", stdin);
freopen("nowhere-zero.out", "w", stdout);
ReadData();
ConstructDualGraph();
FindDualGraphColoring();
PrintSolution();
return 0;
}