#include <bits/stdc++.h>
#define task ""
#define ii pair<int, int>
#define pli pair<long long, int>
#define ll long long
#define ld long double
#define fi first
#define se second
#define faster ios_base::sync_with_stdio(false); cin.tie(nullptr);
#define F if(fopen(task".inp","r")){ freopen(task".inp","r",stdin); freopen(task".out","w",stdout); }

using namespace std;

const int Q = 1e6 + 21;
const int N = 1e5 + 21;
const int LOG = 20;
const int mod = 1e9 + 7;
const int inf = 1e9 + 7;
const int dx[] = {0, 0, 1, -1};
const int dy[] = {1, -1, 0, 0};

int n, m;
vector<int> adj[N];

int deg[N];
int cur_deg[N];

bool rem[N];

int color[N];
int best_k, best[N];

int vis[N], vis_timer = 0;
int in_nei[N], nei_timer = 0;

mt19937 rng(1337);


bool check_bipartite()
{
    if(m == 0)
    {
        best_k = 1;
        for(int i = 1; i <= n; i++) best[i] = 1;
        return true;
    }

    for(int i = 1; i <= n; i++) color[i] = 0;

    for(int i = 1; i <= n; i++)
    {
        if(color[i] != 0) continue;
        color[i] = 1;
        queue<int> q;
        q.push(i);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            for(int v : adj[u])
            {
                if(color[v] == 0)
                {
                    color[v] = 3 - color[u];
                    q.push(v);
                }
                else if(color[v] == color[u])
                {
                    return false;
                }
            }
        }
    }

    best_k = 2;
    for(int i = 1; i <= n; i++) best[i] = color[i];
    return true;
}


bool kempe_color(int u)
{
    vector<int> nei;
    ++nei_timer;
    for(int v : adj[u])
    {
        if(color[v] >= 1 && color[v] <= 4)
        {
            nei.push_back(v);
            in_nei[v] = nei_timer;
        }
    }

    int last_w = -1, last_mask = -1;
    vector<int> q;
    q.reserve(n);

    for(int step = 0; step < 45; step++)
    {
        int cnt[5] = {0, 0, 0, 0, 0};
        int who[5][2];

        for(int v : nei)
        {
            int c = color[v];
            if(c >= 1 && c <= 4)
            {
                if(cnt[c] < 2) who[c][cnt[c]] = v;
                cnt[c]++;
            }
        }

        for(int c = 1; c <= 4; c++)
        {
            if(cnt[c] == 0)
            {
                color[u] = c;
                return true;
            }
        }


        vector<ii> pairs;
        for(int c1 = 1; c1 <= 4; c1++)
        {
            if(cnt[c1] != 1) continue;
            for(int c2 = c1 + 1; c2 <= 4; c2++)
            {
                if(cnt[c2] == 1)
                    pairs.push_back({c1, c2});
            }
            for(int c2 = 1; c2 <= 4; c2++)
            {
                if(cnt[c2] >= 2)
                    pairs.push_back({c1, c2});
            }
        }
        shuffle(pairs.begin(), pairs.end(), rng);

        struct StepBMove { int c1, c2, w; };
        vector<StepBMove> stepB_moves;
        vector<ii> deferred_pairs;

        const int SMALL_LIMIT = 64;


        for(auto &pr : pairs)
        {
            int c1 = pr.fi, c2 = pr.se;
            int start_v = who[c1][0];

            ++vis_timer;
            q.clear();
            q.push_back(start_v);
            vis[start_v] = vis_timer;

            int reached_cnt = 0;
            for(size_t head = 0; head < q.size(); head++)
            {
                int x = q[head];
                for(int y : adj[x])
                {
                    int cy = color[y];
                    if((cy == c1 || cy == c2) && vis[y] != vis_timer)
                    {
                        vis[y] = vis_timer;
                        q.push_back(y);
                        if(in_nei[y] == nei_timer && cy == c2)
                            reached_cnt++;
                    }
                }
                if(reached_cnt == cnt[c2] || (int)q.size() > SMALL_LIMIT)
                    break;
            }

            if(reached_cnt == cnt[c2])
                continue;

            if((int)q.size() <= SMALL_LIMIT)
            {
                if(reached_cnt == 0)
                {
                    for(int x : q) color[x] = (color[x] == c1 ? c2 : c1);
                    color[u] = c1;
                    return true;
                }
                else if(cnt[c2] == 2 && reached_cnt == 1)
                {
                    int w_unreached = (vis[who[c2][0]] == vis_timer) ? who[c2][1] : who[c2][0];
                    stepB_moves.push_back({c1, c2, w_unreached});
                }
            }
            else
            {
                deferred_pairs.push_back(pr);
            }
        }


        for(auto &pr : deferred_pairs)
        {
            int c1 = pr.fi, c2 = pr.se;
            int start_v = who[c1][0];

            ++vis_timer;
            q.clear();
            q.push_back(start_v);
            vis[start_v] = vis_timer;

            int reached_cnt = 0;
            for(size_t head = 0; head < q.size(); head++)
            {
                int x = q[head];
                for(int y : adj[x])
                {
                    int cy = color[y];
                    if((cy == c1 || cy == c2) && vis[y] != vis_timer)
                    {
                        vis[y] = vis_timer;
                        q.push_back(y);
                        if(in_nei[y] == nei_timer && cy == c2)
                            reached_cnt++;
                    }
                }
                if(reached_cnt == cnt[c2])
                    break;
            }

            if(reached_cnt == 0)
            {
                for(int x : q) color[x] = (color[x] == c1 ? c2 : c1);
                color[u] = c1;
                return true;
            }
            else if(cnt[c2] == 2 && reached_cnt == 1)
            {
                int w_unreached = (vis[who[c2][0]] == vis_timer) ? who[c2][1] : who[c2][0];
                stepB_moves.push_back({c1, c2, w_unreached});
            }
        }


        if(stepB_moves.empty()) break;

        shuffle(stepB_moves.begin(), stepB_moves.end(), rng);
        StepBMove chosen = stepB_moves[0];
        for(auto &mv : stepB_moves)
        {
            int mask = (1 << mv.c1) | (1 << mv.c2);
            if(mv.w != last_w || mask != last_mask)
            {
                chosen = mv;
                break;
            }
        }

        ++vis_timer;
        q.clear();
        q.push_back(chosen.w);
        vis[chosen.w] = vis_timer;
        for(size_t head = 0; head < q.size(); head++)
        {
            int x = q[head];
            for(int y : adj[x])
            {
                int cy = color[y];
                if((cy == chosen.c1 || cy == chosen.c2) && vis[y] != vis_timer)
                {
                    vis[y] = vis_timer;
                    q.push_back(y);
                }
            }
        }
        for(int x : q) color[x] = (color[x] == chosen.c1 ? chosen.c2 : chosen.c1);

        last_w = chosen.w;
        last_mask = (1 << chosen.c1) | (1 << chosen.c2);
    }

    return false;
}

void solve()
{
    cin >> n >> m;

    best_k = inf;

    for(int i = 1; i <= n; i++)
    {
        adj[i].clear();
        deg[i] = 0;
        best[i] = 0;
    }

    for(int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        if(u == v) continue;

        adj[u].push_back(v);
        adj[v].push_back(u);
    }


    for(int i = 1; i <= n; i++)
    {
        sort(adj[i].begin(), adj[i].end());
        adj[i].erase(unique(adj[i].begin(), adj[i].end()), adj[i].end());
        deg[i] = adj[i].size();
    }

    if(check_bipartite())
    {
        cout << best_k << '\n';
        for(int i = 1; i <= n; i++) cout << best[i] << " ";
        cout << '\n';
        return;
    }

    clock_t start_time = clock();
    vector<bool> used(n + 2, false);

    while(best_k > 4 && (double)(clock() - start_time) / CLOCKS_PER_SEC < 2.6)
    {
        for(int i = 1; i <= n; i++)
        {
            cur_deg[i] = deg[i];
            rem[i] = false;
            color[i] = 0;
        }


        priority_queue<pli, vector<pli>, greater<pli>> pq;

        for(int i = 1; i <= n; i++)
        {
            pq.push({(1LL * cur_deg[i] << 30) | (rng() & 0x3FFFFFFF), i});
        }

        vector<int> order;
        order.reserve(n);

        while(!pq.empty())
        {
            auto p = pq.top();
            pq.pop();

            int u = p.se;
            if(rem[u]) continue;

            rem[u] = true;
            order.push_back(u);

            for(int v : adj[u])
            {
                if(!rem[v])
                {
                    cur_deg[v]--;
                    pq.push({(1LL * cur_deg[v] << 30) | (rng() & 0x3FFFFFFF), v});
                }
            }
        }

        reverse(order.begin(), order.end());

        int cur_k = 0;

        for(int u : order)
        {
            int mask = 0;
            for(int v : adj[u])
                if(color[v] >= 1 && color[v] <= 4)
                    mask |= (1 << color[v]);

            int chosen_c = 0;
            for(int c = 1; c <= 4; c++)
            {
                if(!(mask & (1 << c)))
                {
                    chosen_c = c;
                    break;
                }
            }

            if(chosen_c > 0)
            {
                color[u] = chosen_c;
            }
            else if(!kempe_color(u))
            {

                for(int v : adj[u])
                    if(color[v] > 0) used[color[v]] = true;
                for(int c = 1; c <= n; c++)
                {
                    if(!used[c])
                    {
                        color[u] = c;
                        break;
                    }
                }
                for(int v : adj[u])
                    if(color[v] > 0) used[color[v]] = false;
            }

            cur_k = max(cur_k, color[u]);
            if(cur_k >= best_k) break;
        }

        if(cur_k < best_k)
        {
            best_k = cur_k;
            for(int i = 1; i <= n; i++)
                best[i] = color[i];
        }
    }

    cout << best_k << '\n';
    for(int i = 1; i <= n; i++)
        cout << best[i] << " ";
    cout << '\n';
}

signed main()
{
    faster;
    F;

    int test = 1;


    while(test--)
    {
        solve();
    }

    cerr << "Time elapsed: " << (1.0 * clock() / CLOCKS_PER_SEC) << " s.\n";

    return 0;
}
