#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <cstring>
#include <set>
using namespace std;
const int N = 100005, M = 3 * N, cMax = 7;
const double Eps = 1e-3;
template<class T>
class Stiva{
T v[N];
int size;
public:
Stiva(){
size = 0;
}
inline void push(T x){
v[++size] = x;
}
inline T top(){
return v[size];
}
inline void pop(){
--size;
}
inline bool empty(){
return size == 0;
}
};
struct Per{
int x, y;
Per(){
x = y = 0;
}
Per(int _x, int _y){
x = _x;
y = _y;
}
inline bool operator<(const Per& N) const {
return x > N.x;
}
};
struct Muchie{
int ind, next;
double alpha;
Muchie(int _ind, int _next, double _alpha){
ind = _ind;
next =_next;
alpha = _alpha;
}
inline bool operator<(const Muchie& M) const {
return alpha < M.alpha;
}
};
int color[N], nrV, nrE, nrC;
double X[N], Y[N];
bool use[N];
vector<int> area[M], comp[M], areaGraph[M];
set<Muchie> graph[N];
Per edge[M];
ifstream in("nowhere-zero.in");
ofstream out("nowhere-zero.out");
inline void addToGraph(int x, int y, int ind, double Y, double X){
graph[x].insert(Muchie(ind, y, atan2(Y, X)));
}
void read(){
int x, y;
in >> nrV >> nrE;
for (int i = 1 ; i <= nrV ; i++)
in >> X[i] >> Y[i];
for (int i = 1 ; i <= nrE ; i++){
in >> x >> y;
edge[i] = Per(x, y);
addToGraph(x, y, i, Y[y] - Y[x], X[y] - X[x]);
addToGraph(y, x, i, Y[x] - Y[y], X[x] - X[y]);
}
}
int mex(vector<int>& v, int val[]){
for (int i = 0 ; i < cMax ; i++)
use[i] = false;
for (vector<int> :: iterator it = v.begin() ; it != v.end() ; it++)
use[ val[*it] ] = true;
for (int i = 1 ; i < cMax ; i++)
if (!use[i])
return i;
return -1;
}
void colorare(vector<int> graph[], int color[], int n){
int grad[n + 1];
priority_queue<Per> Q;
Stiva<int> S;
for (int i = 1 ; i <= n ; i++){
grad[i] = graph[i].size();
Q.push(Per(grad[i], i));
use[i] = false;
}
while (!Q.empty()){
int x = Q.top().y; Q.pop();
if (use[x])
continue;
use[x] = true;
S.push(x);
for (vector<int> :: iterator it = graph[x].begin() ; it != graph[x].end() ; it++){
--grad[*it];
Q.push(Per(grad[*it], *it));
}
}
while (!S.empty()){
color[S.top()] = mex(graph[S.top()], color);
S.pop();
}
}
set<Muchie> :: iterator find(set<Muchie>& S, double alpha){
while (M_PI < alpha)
alpha -= 2 * M_PI;
alpha += Eps;
set<Muchie> :: iterator it = S.upper_bound(Muchie(0, 0, alpha));
for (set<Muchie> :: iterator i = S.begin() ; i != S.end() ; i++)
cout << (i -> next) << " " << (i -> alpha) << "\n";
cout << it -> next << "\n\n";
return it == S.end() ? S.begin() : it;
}
inline int semn(bool b){
return b ? 1 : -1;
}
void expand(set<Muchie>& S, set<Muchie> :: iterator it){
if (it == S.end())
return;
int x = it -> next;
double alpha = it -> alpha;
area[nrC].push_back(it -> ind);
comp[ it -> ind ].push_back(nrC * semn(edge[ it -> ind ].y == x));
S.erase(it);
if (use[x])
return;
use[x] = true;
expand(graph[x], find(graph[x], M_PI + alpha));
use[x] = false;
}
void adauga(int x, int y){
x = abs(x);
y = abs(y);
areaGraph[x].push_back(y);
areaGraph[y].push_back(x);
}
void buildGraph(set<Muchie> graph[]){
memset(use, false, sizeof(use));
for (int i = 1 ; i <= nrV ; i++){
use[i] = true;
while (!graph[i].empty()){
++nrC;
expand(graph[i], graph[i].begin());
}
use[i] = false;
}
for (int i = 1 ; i <= nrE ; i++)
if (comp[i].size() > 1)
adauga(comp[i][0], comp[i][1]);
}
void print(Per P, int x, int y){
int val = 0;
if (x > 0)
val += color[x];
else
val -= color[-x];
if (y > 0)
val += color[y];
else
val -= color[-y];
if (val > 0)
out << P.x << " " << P.y << " " << val << "\n";
else
out << P.y << " " << P.x << " " << -val << "\n";
}
void cleanup(vector<int>& v){
sort(v.begin(), v.end());
int n = 1;
for (int i = 1 ; i < v.size() ; i++)
if (v[i] != v[i - 1])
v[n++] = v[i];
v.resize(n);
}
void printC(vector<int>& v){
for (vector<int> :: iterator it = v.begin() ; it != v.end() ; it++)
cout << edge[*it].x << " " << edge[*it].y << "\n";
cout << "\n";
}
void printCheck(){
cout << nrC << "\n";
for (int i = 1 ; i <= nrC ; i++)
printC(area[i]);
}
int main(){
read();
buildGraph(graph);
printCheck();
for (int i = 1 ; i <= nrC ; i++)
cleanup(areaGraph[i]);
colorare(areaGraph, color, nrC);
for (int i = 1 ; i <= nrE ; i++)
print(edge[i], comp[i][0], comp[i][1]);
return 0;
}