#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;
const int NMAX = 100010, MMAX = 300010, FMAX = 200010;
int N, M, A, B, NrFaces, Deg[FMAX], VertexColor[FMAX], UsedColor[7];
double X[NMAX], Y[NMAX];
pair<int, int> Edges[MMAX], EdgeFaces[MMAX];
vector<pair<int, int> > G[NMAX];
vector<bool> Passed[NMAX];
unordered_set<int> FG[FMAX];
unordered_map<int, int> Idx[NMAX];
vector<int> ColoringOrder;
int Origin;
bool Used[NMAX];
struct Comp
{
bool operator ()(const pair<int, int> &A, const pair<int, int> &B) const
{
return atan2(X[A.second] - X[Origin], Y[A.second] - Y[Origin]) < atan2(X[B.second] - X[Origin], Y[B.second] - Y[Origin]);
}
};
void BuildFG()
{
for(int i = 1; i <= N; ++ i)
{
Origin = i;
sort(G[i].begin(), G[i].end(), Comp());
Passed[i].resize(G[i].size());
for(int j = 0; j < G[i].size(); ++ j)
Idx[i][G[i][j].second] = j;
}
for(int i = 1; i <= N; ++ i)
for(int j = 0; j < G[i].size(); ++ j)
if(!Passed[i][j])
{
NrFaces ++;
int Node = i, Pos = j;
do
{
Passed[Node][Pos] = 1;
int IdxEdge = G[Node][Pos].first, NextNode = G[Node][Pos].second;
if(EdgeFaces[IdxEdge].first == 0) EdgeFaces[IdxEdge].first = NrFaces, Edges[IdxEdge] = make_pair(Node, NextNode);
else EdgeFaces[IdxEdge].second = NrFaces;
Pos = (Idx[NextNode][Node] + 1) % G[NextNode].size();
Node = NextNode;
}while(Node != i);
}
for(int i = 1; i <= M; ++ i)
{
FG[EdgeFaces[i].first].insert(EdgeFaces[i].second);
FG[EdgeFaces[i].second].insert(EdgeFaces[i].first);
}
}
void AssociateColors()
{
set<pair<int, int> > DegSet;
for(int i = 1; i <= NrFaces; ++ i)
{
Deg[i] = FG[i].size();
DegSet.insert(make_pair(Deg[i], i));
}
while(!DegSet.empty())
{
int Node = DegSet.begin() -> second;
DegSet.erase(DegSet.begin());
if(Used[Node]) continue;
Used[Node] = 1;
ColoringOrder.push_back(Node);
for(unordered_set<int> :: iterator it = FG[Node].begin(); it != FG[Node].end(); ++ it)
if(!Used[*it])
{
Deg[*it] --;
DegSet.insert(make_pair(Deg[*it], *it));
}
}
reverse(ColoringOrder.begin(), ColoringOrder.end());
for(int i = 0; i < ColoringOrder.size(); ++ i)
{
int Node = ColoringOrder[i];
for(int i = 1; i <= 6; ++ i)
UsedColor[i] = 0;
for(unordered_set<int> :: iterator it = FG[Node].begin(); it != FG[Node].end(); ++ it)
UsedColor[VertexColor[*it]] = 1;
for(int i = 1; i <= 6; ++ i)
if(!UsedColor[i])
{
VertexColor[Node] = i;
break;
}
}
}
int main()
{
freopen("nowhere-zero.in", "r", stdin);
freopen("nowhere-zero.out", "w", stdout);
scanf("%i %i", &N, &M);
for(int i = 1; i <= N; ++ i) scanf("%lf %lf", &X[i], &Y[i]);
for(int i = 1; i <= M; ++ i)
{
scanf("%i %i", &A, &B);
G[A].push_back(make_pair(i, B));
G[B].push_back(make_pair(i, A));
}
BuildFG();
AssociateColors();
for(int i = 1; i <= M; ++ i)
{
int Dif = VertexColor[EdgeFaces[i].first] - VertexColor[EdgeFaces[i].second];
if(Dif < 0) printf("%i %i %i\n", Edges[i].first, Edges[i].second, -Dif);
else printf("%i %i %i\n", Edges[i].second, Edges[i].first, Dif);
}
}