#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define sz(x) (int)((x).size())
#define all(x) (x).begin(),(x).end()
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
typedef pair< int, int > pii;
typedef pair< long long, long long > pll;
typedef long long ll;
typedef vector< int > vi;
typedef vector< ll > vll;
typedef vector< pii > vpii;
typedef vector< pll > vpll;
typedef long double ld;
typedef vector< ld > vld;
const ll MOD = 1e9 + 9;
ll lgput(ll a, ll b, ll mod) {
ll ret = 1;
while( b ){
if(b & 1) ret = (ret * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return (ret%mod);
}
inline ll inv(ll x, ll MOD) {
return lgput(x, MOD - 2, MOD);
}
const ld PI = acos(-1);
const ld eps = 1e-6;
template <class F>
struct Point {
F x, y;
Point() : x(0), y(0) {}
Point(const F& x, const F& y) : x(x), y(y) {}
void swap(Point& other) { using std::swap; swap(x, other.x); swap(y, other.y); }
template <class F1> explicit operator Point<F1> () const {
return Point<F1>(static_cast<F1>(x), static_cast<F1>(y)); }
template <class F1> Point& operator = (const Point<F1>& other) {
x = other.x; y = other.y; return *this; }
template <class F1> Point& operator += (const Point<F1>& other) {
x += other.x; y += other.y; return *this; }
template <class F1> Point& operator -= (const Point<F1>& other) {
x -= other.x; y -= other.y; return *this; }
template <class F1> Point& operator *= (const F1& factor) {
x *= factor; y *= factor; return *this; }
template <class F1> Point& operator /= (const F1& factor) {
x /= factor; y /= factor; return *this; }
};
template <class F> istream& operator >> (istream& is, Point<F>& point) {
return is >> point.x >> point.y; }
template <class F> ostream& operator << (ostream& os, const Point<F>& point) {
return os << point.x << ' ' << point.y; }
template <class F> inline Point<F> makePoint(const F& x, const F& y) { return Point<F>(x, y); }
template <class F> void swap(Point<F>& lhs, Point<F>& rhs) { lhs.swap(rhs); }
#define FUNC1(name, arg, expr) \
template <class F> inline auto name(const arg) -> decltype(expr) { return expr; }
#define FUNC2(name, arg1, arg2, expr) \
template <class F1, class F2> \
inline auto name(const arg1, const arg2) -> decltype(expr) { return expr; }
#define FUNC3(name, arg1, arg2, arg3, expr) \
template <class F1, class F2, class F3> \
inline auto name(const arg1, const arg2, const arg3) -> decltype(expr) { return expr; }
FUNC1(operator -, Point<F>& point, makePoint(-point.x, -point.y))
FUNC2(operator +, Point<F1>& lhs, Point<F2>& rhs, makePoint(lhs.x + rhs.x, lhs.y + rhs.y))
FUNC2(operator -, Point<F1>& lhs, Point<F2>& rhs, makePoint(lhs.x - rhs.x, lhs.y - rhs.y))
FUNC2(operator *, F1& factor, Point<F2>& rhs, makePoint(factor * rhs.x, factor * rhs.y))
FUNC2(operator *, Point<F1>& lhs, F2& factor, makePoint(lhs.x * factor, lhs.y * factor))
FUNC2(operator /, Point<F1>& lhs, F2& factor, makePoint(lhs.x / factor, lhs.y / factor))
FUNC2(operator *, Point<F1>& lhs, Point<F2>& rhs, lhs.x * rhs.x + lhs.y * rhs.y)
FUNC2(operator ^, Point<F1>& lhs, Point<F2>& rhs, lhs.x * rhs.y - lhs.y * rhs.x)
// < 0 if rhs <- lhs counter-clockwise, 0 if collinear, > 0 if clockwise.
FUNC2(ccw, Point<F1>& lhs, Point<F2>& rhs, rhs ^ lhs)
FUNC3(ccw, Point<F1>& lhs, Point<F2>& rhs, Point<F3>& origin, ccw(lhs - origin, rhs - origin))
FUNC2(operator ==, Point<F1>& lhs, Point<F2>& rhs, lhs.x == rhs.x && lhs.y == rhs.y)
FUNC2(operator !=, Point<F1>& lhs, Point<F2>& rhs, !(lhs == rhs))
FUNC2(operator <, Point<F1>& lhs, Point<F2>& rhs,
lhs.y < rhs.y || (lhs.y == rhs.y && lhs.x < rhs.x))
FUNC2(operator >, Point<F1>& lhs, Point<F2>& rhs, rhs < lhs)
FUNC2(operator <=, Point<F1>& lhs, Point<F2>& rhs, !(lhs > rhs))
FUNC2(operator >=, Point<F1>& lhs, Point<F2>& rhs, !(lhs < rhs))
// Angles and rotations (counter-clockwise).
FUNC1(angle, Point<F>& point, atan2(point.y, point.x))
FUNC2(angle, Point<F1>& lhs, Point<F2>& rhs, atan2(lhs ^ rhs, lhs * rhs))
FUNC3(angle, Point<F1>& lhs, Point<F2>& rhs, Point<F3>& origin,
angle(lhs - origin, rhs - origin))
FUNC3(rotate, Point<F1>& point, F2& angleSin, F3& angleCos,
makePoint(angleCos * point.x - angleSin * point.y,
angleSin * point.x + angleCos * point.y))
FUNC2(rotate, Point<F1>& point, F2& angle, rotate(point, sin(angle), cos(angle)))
FUNC3(rotate, Point<F1>& point, F2& angle, Point<F3>& origin,
origin + rotate(point - origin, angle))
FUNC1(perp, Point<F>& point, makePoint(-point.y, point.x))
// Distances.
FUNC1(abs, Point<F>& point, point * point)
FUNC1(norm, Point<F>& point, sqrt(abs(point)))
FUNC2(dist, Point<F1>& lhs, Point<F2>& rhs, norm(lhs - rhs))
FUNC2(dist2, Point<F1>& lhs, Point<F2>& rhs, abs(lhs - rhs))
FUNC2(bisector, Point<F1>& lhs, Point<F2>& rhs, lhs * norm(rhs) + rhs * norm(lhs))
template <class F>
struct Line {
Point<F> a, ab;
Line() : a(), ab() {}
Line(const Point<F>& a, const Point<F>& b, bool twoPoints = true)
: a(a), ab(twoPoints ? b - a : b) {}
Line(const F& xa, const F& ya, const F& xb, const F& yb)
: a(xa, ya), ab(xb - xa, yb - ya) {}
void swap(Line& other) { using std::swap; swap(a, other.a); swap(ab, other.ab); }
template <class F1> explicit operator Line<F1> () const {
return Line<F1>(Point<F1>(a), Point<F1>(ab), false); }
template <class F1> Line& operator = (const Line<F1>& other) {
a = other.a; ab = other.ab; return *this; }
Point<F> b() const { return a + ab; }
operator bool () const { return ab != Point<F>(); }
};
template <class F1, class F2> using distF = decltype(sqrt(F1() + F2()));
template <class F1, class F2>
distF<F1, F2> distLine(const Point<F1>& point, const Line<F2>& line) {
if (!line) return dist(point, line.a);
return abs((point - line.a) ^ line.ab) / norm(line.ab);
}
template <class F1, class F2>
distF<F1, F2> distSegment(const Point<F1>& point, const Line<F2>& seg) {
if (((point - seg.a) * seg.ab) <= 0) return dist(point, seg.a);
if (((point - seg.b()) * seg.ab) >= 0) return dist(point, seg.b());
return distLine(point, seg);
}
const int MAXN = 8200;
vector< int > gr[MAXN];
int l[MAXN];
int r[MAXN];
int cl[MAXN];
int cr[MAXN];
int viz[MAXN];
int step = 1;
int matched = 0;
bool cuplaj(int node) {
if(viz[node] == step) return false;
viz[node] = step;
for(auto &x : gr[node]) {
if(!r[x] || cuplaj(r[x])) {
if(!r[x]) matched ++;
r[x] = node;
l[node] = x;
return true;
}
}
return false;
}
void dfs(int node) {
for(auto &x : gr[node]) {
if(!cr[x]) {
cr[x] = 1;
cl[r[x]] = 0;
dfs(r[x]);
}
}
}
int main() {
///COMENTEAZA MA
#ifndef ONLINE_JUDGE
//freopen("input", "r", stdin);
#endif
///COMENTEAZA MA
FO(felinare)
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout.precision(12);
cout.fixed;
int n, m;
cin >> n >> m;
for(int i = 0; i < m; ++i) {
int a, b;
cin >> a >> b;
gr[a].emplace_back(b);
}
for(bool ok = true; ok; ++step) {
ok = false;
for(int i = 1; i <= n; ++i) {
if(!l[i]) ok |= cuplaj(i);
}
}
for(int i = 1; i <= n; ++i) {
if(l[i]) cl[i] = 1;
}
for(int i = 1; i <= n; ++i) {
if(!l[i]) dfs(i);
}
cout << 2*n - matched << '\n';
for(int i = 1; i <= n; ++i) {
cout << 3 - cl[i] - cr[i]*2 << '\n';
}
return 0;
}