#include <bits/stdc++.h>
using namespace std;
struct UnionFind {
  vector<int> data;
  UnionFind(int sz) { data.assign(sz, -1); }
  int find(int k) { return (data[k] < 0 ? k : data[k] = find(data[k])); }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (data[x] > data[y]) swap(x, y);
    data[x] += data[y];
    data[y] = x;
  }
};
struct edge {
  int to, type, idx;
};
int N, M;
vector<edge> g[100000];
int sz[100000], cmp[100000];
bool v[100000];
vector<int> G[100000], RG[100000], order;
void dfs(int idx) {
  if (v[idx]++) return;
  for (auto &to : G[idx]) dfs(to);
  order.push_back(idx);
}
void rdfs(int idx, int k) {
  cmp[idx] = k;
  for (auto &to : RG[idx])
    if (cmp[to] == -1) rdfs(to, k);
}
void dfs2(int idx, int par) {
  sz[idx] = 1;
  for (auto &e : g[idx]) {
    if (e.to == par) continue;
    if (!e.type) {
      dfs2(e.to, idx);
      sz[idx] = max(sz[idx], sz[e.to] + 1);
    }
  }
}
int getUQ(vector<pair<int, int> > &s, int idx) {
  if (s[0].second == idx) return (s[1].first);
  return (s[0].first);
}
int rec(int idx, int par, int pardist) {
  v[idx] = true;
  vector<pair<int, int> > ei;
  ei.emplace_back(pardist, -1);
  for (auto &e : g[idx]) {
    if (e.to == par) continue;
    ei.emplace_back(e.type ? 0 : sz[e.to] + 1, e.to);
  }
  sort(ei.rbegin(), ei.rend());
  int ret = pardist;
  for (auto &e : g[idx]) {
    if (e.to == par) continue;
    if (e.type) ret = max(ret, rec(e.to, idx, getUQ(ei, e.to) + 1));
  }
  return (ret);
}
int main() {
  scanf("%d %d", &N, &M);
  UnionFind tree(N);
  for (int i = 0; i < M; i++) {
    int X, Y, W;
    scanf("%d %d %d", &X, &Y, &W);
    --X, --Y;
    g[X].push_back((edge){Y, 1, i});
    g[Y].push_back((edge){X, W == 2, i});
    if (W == 1) {
      G[X].push_back(Y);
      RG[Y].push_back(X);
    } else if (W == 2) {
      if (tree.find(X) == tree.find(Y)) {
        cout << "Infinite" << endl;
        return (0);
      }
      tree.unite(X, Y);
    }
  }
  for (int i = 0; i < N; i++) dfs(i);
  reverse(begin(order), end(order));
  int kk = 0;
  memset(cmp, -1, sizeof(cmp));
  for (auto &v : order)
    if (cmp[v] == -1) rdfs(v, kk++);
  if (kk != N) {
    cout << "Infinite" << endl;
    return (0);
  }
  int ret = 0;
  memset(v, false, sizeof(v));
  for (int i = 0; i < N; i++) {
    if (v[i]++) continue;
    dfs2(i, -1);
    ret = max(ret, rec(i, -1, 0));
  }
  printf("%d\n", ret);
}
