#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const double esp = 1e-8;
#define Fact(x) ((x)*(x))
//一般图匹配带花树
const int MaxN = 111;
int N;
bool Graph[MaxN][MaxN];
int Match[MaxN];
bool InQueue[MaxN], InPath[MaxN], InBlossom[MaxN];
int Head, Tail;
int Queue[MaxN];
int Start, Finish;
int NewBase;
int Father[MaxN], Base[MaxN];
int Count;
void CreateGraph()
{
int u, v;
memset(Graph,false,sizeof(Graph));
scanf("%d", &N);
while( scanf("%d", &N) );
while( scanf("%d%d", &u,&v) != EOF )
Graph[u][v] = Graph[v][u] = true;
}
void Push(int u)
{
Queue[Tail] = u;
Tail ++;
InQueue[u] = true;
}
int Pop()
{
int res = Queue[Head];
Head++;
return res;
}
int FindCommonAncestor(int u,int v)
{
memset( InPath, false, sizeof(InPath));
while( true )
{
u = Base[u];
InPath[u] = true;
if( u == Start ) break;
u = Father[ Match[u] ];
}
while( true )
{
v = Base[v];
if( InPath[v] ) break;
v = Father[ Match[v] ];
}
return v;
}
void ResetTrace(int u)
{
int v;
while( Base[u] != NewBase )
{
v = Match[u];
InBlossom[ Base[u] ] = InBlossom[ Base[v] ] = true;
u = Father[v];
if( Base[u] != NewBase ) Father[u] = v;
}
}
void BlossomContract(int u,int v)
{
NewBase = FindCommonAncestor(u,v);
memset( InBlossom, false, sizeof(InBlossom ));
ResetTrace(u);
ResetTrace(v);
if( Base[u] != NewBase ) Father[u] = v;
if( Base[v] != NewBase ) Father[v] = u;
for(int tu = 1; tu <= N; tu++)
if( InBlossom[Base[tu]] )
{
Base[tu] = NewBase;
if( !InQueue[tu] ) Push(tu);
}
}
void FindAugmentingPath()
{
memset(InQueue,false,sizeof(InQueue));
memset(Father,0,sizeof(Father));
for(int i = 1; i <= N; i++)
Base[i] = i;
Head = Tail = 1;
Push( Start );
Finish = 0;
while( Head < Tail )
{
int u = Pop();
for(int v = 1; v <= N; v++)
if( Graph[u][v] && (Base[u]!=Base[v]) && (Match[u]!=v) )
{
if( (v==Start) ||
( (Match[v]>0)&&(Father[Match[v]]>0) ) )
BlossomContract(u,v);
else if( Father[v] == 0 )
{
Father[v] = u;
if( Match[v] > 0 )
Push(Match[v]);
else
{
Finish = v;
return;
}
}
}
}
}
void AugmentPath()
{
int u, v, w;
u = Finish;
while( u > 0 )
{
v = Father[u];
w = Match[v];
Match[v] = u;
Match[u] = v;
u = w;
}
}
void Edmonds()
{
memset( Match,0,sizeof(Match));
for(int u = 1; u <= N; u++)
{
if( Match[u] == 0 )
{
Start = u;
FindAugmentingPath();
if( Finish > 0 ) AugmentPath();
}
}
}
void PrintMatch(){
Count = 0;
for(int u = 1; u <= N; u++)
if( Match[u] > 0 )
Count++;
printf("%d\n", Count );
for(int u = 1; u <= N; u++)
if( u < Match[u] )
printf("%d %d\n", u, Match[u] );
}
struct Point{
int x, y;
Point(){}
Point(int _x,int _y):x(_x),y(_y){}
Point operator - (const Point &b)const{
return Point(x-b.x,y-b.y);
}
int operator * (const Point &b)const{
return x*b.y-b.x*y;
}
double operator &(const Point &b)const{
return x*b.x+y*b.y;
}
};
struct Line{
Point s, e;
double k;
Line(){}
Line(Point _s,Point _e){
s = _s; e = _e;
}
};
int sign(double x){ return x<-esp?-1:(x>esp);}
double dist(Point a,Point b) {
return sqrt( Fact(a.x-b.x) + Fact(a.y-b.y) );
}
bool inter(Line l1, Line l2)
{
return
max(l1.s.x,l1.e.x) >= min( l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.y) >= min( l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min( l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min( l1.s.y,l1.e.y) &&
sign( (l2.s-l1.s)*(l1.e-l1.s) )*sign( (l2.e-l1.s)*(l1.e-l1.s) ) <= 0 &&
sign( (l1.s-l2.s)*(l2.e-l2.s) )*sign( (l1.e-l2.s)*(l2.e-l2.s) ) <= 0;
}
void gao(){
CreateGraph();
Edmonds();
PrintMatch();
}