#include <iostream>
#include <cstring>
#include <vector>
#include <stack>
#include <queue>
#include <set>

#ifdef ONLINE_JUDGE
#define cerr if(0)cerr
#endif

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<int, pii> edg;

const int maxn = 210;
const int maxm = 2012;

edg G_edges[maxm];
edg H_edges[maxm];
vector<int> G[maxn];
vector<int> H[maxn];
int dist[maxn][maxn]; // in H
bool vis[maxn];
bool color[maxn];
int edcnt_H = 0;

int n, m;

inline int get_other(int i, int v, edg arr[])
{
	if(arr[i].second.first == v)
		return arr[i].second.second;
	return arr[i].second.first;
}

inline void add_edge_H(int x, int y, int w)
{
	H_edges[edcnt_H] = {w, {x, y}};
	H[x].push_back(edcnt_H);
	dist[x][y] = w;
	edcnt_H++;
	cerr << "adding " << x << " " << y << " " << w << endl;
}

inline void fill_H()
{
	for(int i = 0; i < m; i++)
	{
		int x = G_edges[i].second.first;
		int y = G_edges[i].second.second;
		if(G_edges[i].first == 1)
		{
			add_edge_H(x, y, 1);
			add_edge_H(y, x, -1);
		}
		else
		{
			add_edge_H(x, y, 1);
			add_edge_H(y, x, 1);
		}
	}
}


inline bool check_bipar()
{
	stack<int> ds;
	ds.push(0);
	vis[0] = true;
	color[0] = 0;
	while(!ds.empty())
	{
		int t = ds.top(); ds.pop();
		for(int i: G[t])
		{
			int u = get_other(i, t, G_edges);
			if(vis[u])
			{
				if(color[u] == color[t])
					return false;
				continue;
			}
			ds.push(u);
			vis[u] = true;
			color[u] = !color[t];
		}
	}
	return true;
}

inline void floyd_warshall()
{
	for(int i = 0; i < n; i++)
		dist[i][i] = 0;
	for(int k = 0; k < n; k++)
		for(int i = 0; i < n; i++)
			for(int j = 0; j < n; j++)
				dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j]);
}

inline void die()
{
	cout << "NO" << endl;
	exit(0);
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n >> m;
	memset(dist, 63, sizeof dist);
	for(int i = 0; i < m; i++)
	{
		int x, y, b;
		cin >> x >> y >> b;
		x--; y--;
		G_edges[i] = {b, {x, y}};
		G[x].push_back(i);
		G[y].push_back(i);
	}
	bool bip = check_bipar();
	cerr << "bipar: " << bip << endl;
	if(!bip)
		die();
	fill_H();
	for(int i = 0; i < n; i++)
	{
		cerr << i+1 << ": ";
		for(int j: H[i])
		{
			int u = get_other(j, i, H_edges);
			int w = H_edges[i].first;
			cerr << u+1 << "," << w << "  ";
		}
		cerr << endl;
	}
	floyd_warshall();
	cerr << endl;
	for(int i = 0; i < n; i++)
	{
		cerr << i << ": ";
		for(int j = 0; j < n; j++)
			cerr << dist[i][j] << " ";
		cerr << endl;
	}
	int max_dist = 0;
	int source = 0;
	int destin = 0;
	for(int i = 0; i < n; i++)
	{
		if(dist[i][i] < 0)
			die();
		for(int j = 0; j < n; j++)
		{
			if(dist[i][j] > max_dist)
			{
				max_dist = dist[i][j];
				source = i;
				destin = j;
			}
		}
	}
	cout << "YES" << endl;
	cout << max_dist << endl;
	for(int i = 0; i < n; i++)
	{
		cout << dist[source][i] << " ";
	}
	cout << endl;
	return 0;
}
