#include <bits/stdc++.h>
using namespace std;
#define endl '\n'

int main() {
    cin.tie(0)->sync_with_stdio(0);

    int n, m; cin >> n >> m;
    vector<vector<int>> g(n);

    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v;
        u--; v--;
        g[u].push_back(v);
    }

    vector<int> output, visited(n, 0);
    auto dfs = [&](int v, vector<int>& order, vector<vector<int>>& adj, auto&& self) -> void {
        visited[v] = 1;
        for (auto u : adj[v]) {
            if (!visited[u]) {
                self(u, order, adj, self);
            }
        }
        order.push_back(v);
    };

    vector<vector<int>> components, g_cond;
    vector<int> roots(n, 0);
    auto scc = [&]() -> void {
        for (int i = 0; i < n; i++) {
            if (!visited[i]) dfs(i, output, g, dfs);
        }

        vector<vector<int>> g_rev(n);
        for (int v = 0; v < n; v++) {
            for (int u : g[v]) {
                g_rev[u].push_back(v);
            }
        }

        visited.assign(n, 0);
        reverse(output.begin(), output.end());

        for (auto v : output) {
            if (!visited[v]) {
                vector<int> component;
                dfs(v, component, g_rev, dfs);
                int root = components.size();
                components.push_back(component);
                for (auto u : component) roots[u] = root;
            }
        }

        g_cond.assign(components.size(), {});

        for (int v = 0; v < n; v++) {
            for (auto u : g[v]) {
                if (roots[v] != roots[u]) {
                    g_cond[roots[v]].push_back(roots[u]);
                }
            }
        }
    };
    scc();

    vector<int> indeg(g_cond.size(), 0), top_ord;
    for (auto& v : g_cond) for (auto x : v) indeg[x]++;

    queue<int> q;
    for (int i = 0; i < g_cond.size(); i++) if (indeg[i] == 0) q.push(i);

    while (!q.empty()) {
        int i = q.front(); q.pop(); top_ord.push_back(i);
        for (int x : g_cond[i]) if (--indeg[x] == 0) q.push(x);
    }

    int mmc = 1;
    for (int i = 0; i < components.size(); i++) {
        int size = components[i].size();
        mmc = mmc / gcd(mmc, size) * size;
        if(size==1)
            continue;
        int edg = 0;
        for(int x:components[i])
        {
            for(int y:g[x])
                if(roots[x]==roots[y])
                    edg++;
        }
            
        if(edg!=components[i].size())
        {
            cout<<"NO"<<endl;
            return 0;
        }
    }

    assert(mmc <= 50000);

    cout << "YES" << endl << mmc << endl;

    for (int i = 0; i < mmc; i++) {
        for (int t : top_ord) {
            auto& c = components[t];
            for (auto el : c) cout << el + 1 << ' ';
        }
        cout << endl;
        for (auto& c : components) {
            int tmp = c.front();
            for (int i = 0; i < c.size() - 1; i++) c[i] = c[i+1];
            c.back() = tmp;
        }
    }

    return 0;
}