#include <bits/stdc++.h>
using namespace std;
template<class T> inline bool chmax(T& a, T b) { 
    if (a < b) { a = b; return 1; } 
    return 0; 
}
template<class T> inline bool chmin(T& a, T b) { 
    if (a > b) { a = b; return 1; } 
    return 0; 
}

struct UnionFind {
    vector<int> par;

    UnionFind() { }
    UnionFind(int n) : par(n, -1) { }
    void init(int n) { par.assign(n, -1); }
    
    int root(int x) {
        if (par[x] < 0) return x;
        else return par[x] = root(par[x]);
    }
    
    bool issame(int x, int y) {
        return root(x) == root(y);
    }
    
    bool merge(int x, int y) {
        x = root(x); y = root(y);
        if (x == y) return false;
        if (par[x] > par[y]) swap(x, y); // merge technique
        par[x] += par[y];
        par[y] = x;
        return true;
    }
    
    int size(int x) {
        return -par[root(x)];
    }
};

const int INF = 1<<29;
int main() {
    auto solve = [&]() -> bool {
        int N, M;
        cin >> N >> M;
        UnionFind uf(N*2);
        vector<vector<int>> dp(N, vector<int>(N, INF));
        for (int i = 0; i < N; ++i) dp[i][i] = 0;
        for (int i = 0; i < M; ++i) {
            int u, v, c;
            cin >> u >> v >> c;
            --u, --v;
            uf.merge(u, v+N), uf.merge(v, u+N);
            if (c == 1) dp[u][v] = 1, dp[v][u] = -1;
            else dp[u][v] = dp[v][u] = 1;
        }
        for (int k = 0; k < N; ++k)
            for (int i = 0; i < N; ++i)
                for (int j = 0; j < N; ++j)
                    chmin(dp[i][j], dp[i][k] + dp[k][j]);

        // 二部グラフ判定, 負閉路存在判定
        for (int v = 0; v < N; ++v) {
            if (uf.issame(v, v+N)) return false;
            if (dp[v][v] < 0) return false;
        }

        // 牛ゲー
        int vmax = 0, pmax = 0;
        for (int s = 0; s < N; ++s) {
            int tmp = 0;
            for (int t = 0; t < N; ++t) chmax(tmp, dp[s][t]);
            if (chmax(vmax, tmp)) pmax = s;
        }
        cout << "YES" << endl << vmax << endl;
        for (int v = 0; v < N; ++v) cout << dp[pmax][v] << " ";
        cout << endl;
        return true;
    };
    if (!solve()) cout << "NO" << endl;
}