/* OBS.
* a -> prietenul a vine la party
* a + n -> prietenul a nu vine la party
*
*/
#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
using namespace std;
using VI = vector<int>;
using VB = vector<bool>;
using VVI = vector<VI>;
ifstream fin("party.in");
ofstream fout("party.out");
int n, m;
int idx, total;
VI index, low, id;
VB in_stack;
VVI G;
stack<int> stk;
void ReadInput();
void Solve();
void DFS(int node);
void ExtractCTC(int node);
int main()
{
ReadInput();
Solve();
return 0;
}
void Solve()
{
for (int node = 1; node <= 2 * n; ++node)
if (!index[node])
DFS(node);
VI ans;
for (int node = 1; node <= n; ++node)
if (id[node] == id[node + n])
{
fout << 0;
return;
}
else if (id[node] < id[node + n])
ans.push_back(node);
fout << ans.size() << '\n';
for (int node : ans)
fout << node << '\n';
}
void DFS(int node)
{
index[node] = low[node] = ++idx;
stk.push(node);
in_stack[node] = true;
for (int nbr : G[node])
if (!index[nbr])
{
DFS(nbr);
low[node] = min(low[node], low[nbr]);
}
else if (in_stack[nbr])
low[node] = min(low[node], index[nbr]);
if (index[node] == low[node])
ExtractCTC(node);
}
void ExtractCTC(int node)
{
total++;
int next;
while (!stk.empty())
{
next = stk.top();
stk.pop();
in_stack[next] = false;
id[next] = total;
if (next == node)
break;
}
}
void ReadInput()
{
fin >> n >> m;
index = low = id = VI(2 * n + 1);
in_stack = VB(2 * n + 1);
G = VVI(2 * n + 1);
int u, v, type;
while (m--)
{
fin >> u >> v >> type;
cout << u << ' ' << v << ' ' << u + n << ' ' << u + v << '\n';
if (type == 0)
{
G[u + n].push_back(v);
G[v + n].push_back(u);
}
else if (type == 1)
{
G[u + n].push_back(v + n);
G[v].push_back(u);
}
else if (type == 2)
{
G[v + n].push_back(u + n);
G[u].push_back(v);
}
else
{
G[u].push_back(v + n);
G[v].push_back(u + n);
}
}
}