Pagini recente » Cod sursa (job #1729170) | Cod sursa (job #1016948) | Cod sursa (job #2275792) | Cod sursa (job #2887071) | Cod sursa (job #962267)
Cod sursa(job #962267)
#include <cstdio>
#include <cmath>
#include <cassert>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <unordered_set>
using namespace std;
typedef long long int64;
class Point {
public:
double x, y;
Point() {}
Point(const double x, const double y) {
this->x = x;
this->y = y;
}
};
class Edge {
public:
int x, y;
Edge() {}
Edge(const int x, const int y) {
this->x = x;
this->y = y;
}
bool operator==(const Edge &other) const {
return (x == other.x && y == other.y);
}
static Edge Reverse(const Edge &e) {
return Edge(e.y, e.x);
}
class HashCode {
public:
int operator()(const Edge &object) const {
return (1LL * object.x * Base + object.y) % U;
}
private:
static const int Base = 100003;
static const int U = 666013;
};
};
vector<Point> Points;
vector<double> Alpha;
vector<vector<int>> G, RegionG;
int V, E;
unordered_map<Edge, int, Edge::HashCode> Next, RegionIndex, Flow;
vector<vector<int>> Regions;
vector<Edge> Edges;
class Compare {
public:
bool operator()(const int &x, const int &y) const {
return Alpha[x] < Alpha[y];
}
};
void BuildGraph() {
for (int x = 0; x < V; ++x) {
if (G[x].empty())
continue;
for (auto &y: G[x])
Alpha[y] = atan2(Points[y].y - Points[x].y, Points[y].x - Points[x].x);
sort(G[x].begin(), G[x].end(), Compare());
G[x].push_back(G[x].front());
for (int i = 0; i + 1 < static_cast<int>(G[x].size()); ++i)
Next[Edge(G[x][i], x)] = G[x][i + 1];
}
}
void BuildRegions() {
unordered_set<Edge, Edge::HashCode> usedEdges;
for (int x = 0; x < V; ++x) {
for (auto &y: G[x]) {
Edge e = Edge(x, y);
if (usedEdges.find(e) != usedEdges.end())
continue;
vector<int> region;
region.push_back(x);
do {
usedEdges.insert(e);
RegionIndex[e] = static_cast<int>(Regions.size());
region.push_back(e.y);
e = Edge(e.y, Next[e]);
} while (usedEdges.find(e) == usedEdges.end());
Regions.push_back(region);
}
}
}
void BuildRegionGraph() {
RegionG.resize(Regions.size());
unordered_set<Edge, Edge::HashCode> usedEdges;
for (auto e: Edges) {
int x = RegionIndex[e], y = RegionIndex[Edge::Reverse(e)];
if (usedEdges.find(Edge(x, y)) != usedEdges.end())
continue;
RegionG[x].push_back(y); RegionG[y].push_back(x);
usedEdges.insert(Edge(x, y)); usedEdges.insert(Edge(y, x));
}
}
void Solve() {
BuildGraph();
BuildRegions();
BuildRegionGraph();
}
void Read() {
assert(freopen("nowhere-zero.in", "r", stdin));
assert(scanf("%d %d", &V, &E) == 2);
G.resize(V);
Points.resize(V);
Alpha.resize(V);
Edges.resize(E);
for (int i = 0; i < V; ++i)
assert(scanf("%lf %lf", &Points[i].x, &Points[i].y) == 2);
for (int i = 0; i < E; ++i) {
int x, y; assert(scanf("%d %d", &x, &y) == 2);
--x; --y;
Edges[i] = Edge(x, y);
Flow[Edge(x, y)] = Flow[Edge(y, x)] = 0;
G[x].push_back(y); G[y].push_back(x);
}
}
void Print() {
assert(freopen("nowhere-zero.out", "w", stdout));
for (auto e: Edges) {
if (Flow[e] < 0)
e = Edge::Reverse(e);
printf("%d %d %d\n", e.x + 1, e.y + 1, Flow[e]);
}
}
int main() {
Read();
Solve();
Print();
return 0;
}