#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
#define MaxN 100100
#define STARTER -MaxN
#define sqr(x) ((x) * (x))
struct Edge {
int vec, flux;
Edge(int v) {
vec = v;
flux = 0;
}
};
pair<double, double> points[MaxN];
int perm[MaxN];
int N, M, doneEdges = 0;
vector<Edge> edges[MaxN];
int cd[MaxN], t[MaxN];
bool viz[MaxN], haveTouched[MaxN];
int startNode = 0, sizeCd = 0;
bool stillCycling;
void SetTata(int poz, int val) {
t[poz] = val;
cd[sizeCd++] = poz;
}
void ClearTati() {
for (int i = 0; i < sizeCd; i++) {
t[cd[i]] = -1;
}
sizeCd = 0;
}
bool CompFlux(const Edge &a, const Edge &b) {
return a.flux < b.flux;
}
double GetDist(int x, const Edge &a) {
const int y = a.vec;
return sqrt(sqr(points[x].first - points[y].first) + sqr(points[x].first - points[y].first));
}
bool CompFluxDist(const Edge &a, const Edge &b) {
if (a.flux != b.flux) {
return a.flux < b.flux;
} else {
return GetDist(startNode, a) < GetDist(startNode, b);
}
}
void IncremFlow(int x, int y, int flux) {
for (size_t i = 0; i < edges[x].size(); i++) {
if (edges[x][i].vec == y) {
doneEdges += (edges[x][i].flux == 0 && flux > 0);
edges[x][i].flux += flux;
return;
}
}
}
void MarkEdge(int x, int y) {
IncremFlow(x, y, 1);
IncremFlow(y, x, -1);
}
bool HaveEdges(int x) {
for (size_t i = 0; i < edges[x].size(); i++) {
if (edges[x][i].flux == 0) {
return true;
}
}
return false;
}
void ReversePath(int nod, int startNode) {
MarkEdge(nod, startNode);
while (nod != startNode) {
MarkEdge(t[nod], nod);
nod = t[nod];
}
}
//ar trebui facute mai multe cautari in acelasi timp
void df(int nod) {
int nrEmpty = 0, nrVec = (int)edges[nod].size();
for (int i = 0; i < nrVec; i++) {
if (edges[nod][i].flux == 0) {
swap(edges[nod][nrEmpty++], edges[nod][i]);
}
}
Edge *curEdges = &edges[nod][0];
if (nrEmpty) {
sort(curEdges, curEdges + nrEmpty, CompFluxDist);
} else {
//random_shuffle(curEdges + nrEmpty, curEdges + nrVec);
//sort(curEdges, curEdges + nrVec, CompFlux);
}
for (int i = 0; i < nrVec && stillCycling; i++) {
const int vec = edges[nod][i].vec;
if (edges[nod][i].flux >= 0 && t[vec] == -1 && vec != t[nod]) {
if (vec == startNode) {
stillCycling = false;
ReversePath(nod, startNode);
return;
}
SetTata(vec, nod);
df(vec);
}
}
}
void FindCycle() {
while (!HaveEdges(startNode) && startNode < N) {
startNode++;
}
stillCycling = true;
for (size_t i = 0; i < edges[startNode].size(); i++) {
if (edges[startNode][i].flux == 0) {
const int v = edges[startNode][i].vec;
SetTata(v, startNode);
df(v);
ClearTati();
return;
}
}
}
void FindCyclesBF() {
int st = 0, fn = 0;
int nrStarters = (int) sqrt(N) + 1;
random_shuffle(perm, perm + N);
for (int i = 0; i < N && nrStarters > 0; i++) {
int nod = perm[i];
if (HaveEdges(nod)) {
nrStarters--;
t[nod] = STARTER;
for (size_t j = 0; j < edges[nod].size(); j++) {
const int v = edges[nod][j].vec;
if (edges[nod][j].flux == 0 && t[v] == -1) {
cd[fn++] = v;
t[v] = nod;
}
}
}
}
while (st < fn) {
int nod = cd[st++];
for (size_t i = 0; i < edges[nod].size(); i++) {
const int v = edges[nod][i].vec;
if (edges[nod][i].flux >= 0 && v != t[nod] && t[v] < 0) {
if (t[v] == STARTER) {
ReversePath(nod, v);
} else {
t[v] = nod;
cd[fn++] = v;
}
}
}
}
memset(t, -1, sizeof(int) * N);
}
void Gen() {
FILE *out = fopen("nowhere-zero.in", "wb");
int N = 100;
fprintf(out, "%d %d\n", N*N, 2*N*N - 2*N);
#define Index(i, j) ((i) * N + j + 1)
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
fprintf(out, "%d %d\n", i, j);
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (i + 1 < N) {
fprintf(out, "%d %d\n", Index(i, j), Index(i + 1, j));
}
if (j + 1 < N) {
fprintf(out, "%d %d\n", Index(i, j), Index(i, j + 1));
}
}
}
fclose(out);
}
int main() {
//Gen();
freopen("nowhere-zero.in", "rb", stdin);
freopen("nowhere-zero.out", "wb", stdout);
scanf("%d %d\n", &N, &M);
for (int i = 0; i < N; i++) {
scanf("%lf %lf", &points[i].first, &points[i].second);
perm[i] = i;
}
for (int i = 0; i < M; i++) {
int x, y;
scanf("%d %d", &x, &y);
x--; y--;
edges[x].push_back(y);
edges[y].push_back(x);
}
memset(t, -1, sizeof(int) * N);
int iter = 0;
while (doneEdges < M) {
FindCycle();
iter++;
}
fprintf(stderr, "%d Iter\n");
for (int i = 0; i < N; i++) {
for (size_t j = 0; j < edges[i].size(); j++) {
if (edges[i][j].flux > 0) {
printf("%d %d %d\n", i + 1, edges[i][j].vec + 1, edges[i][j].flux);
}
}
}
return 0;
}