#include <bits/stdc++.h>
using namespace std;
int counter;
struct directed_graph {
  int n;
  vector<int> edge[100001 + 5];
  vector<int> indx[100001 + 5];
  short int clr[100001 + 5];
  bool flag;
  directed_graph(int _n = 0) { n = _n; }
  void addEdge(int u, int v) {
    edge[u].push_back(v);
    indx[u].push_back(++counter);
  }
  void dfs(int idx) {
    if (clr[idx] == 1) {
      flag = true;
      return;
    }
    if (flag == true) return;
    if (clr[idx]) return;
    clr[idx] = 1;
    for (auto x : edge[idx]) dfs(x);
    clr[idx] = 2;
  }
  bool hasCycle() {
    flag = false;
    memset(clr, 0, sizeof(clr));
    for (int i = 1; i <= n; i++)
      if (clr[i] == 0) dfs(i);
    return flag;
  }
} dg, cmpg;
struct undirected_graph {
  int n, d[100001 + 5];
  vector<int> edge[100001 + 5], indx[100001 + 5];
  bool vis[100001 + 5];
  bool flag;
  int tab[18 + 2][100001 + 5];
  int par[100001 + 5];
  int lev[100001 + 5], stp;
  undirected_graph(int _n = 0) {
    n = _n;
    memset(d, -1, sizeof(d));
  }
  void addEdge(int u, int v) {
    edge[u].push_back(v);
    edge[v].push_back(u);
    indx[u].push_back(++counter);
    indx[v].push_back(++counter);
  }
  int bfs(int idx) {
    int mx = 0, ret = idx;
    queue<int> q;
    d[idx] = 0;
    q.push(idx);
    while (!q.empty()) {
      int u = q.front();
      q.pop();
      for (auto x : edge[u])
        if (d[x] == -1) {
          d[x] = d[u] + 1;
          q.push(x);
          if (d[x] > mx) {
            mx = d[x];
            ret = x;
          }
        }
    }
    return ret;
  }
  void init_st(int n) {
    int idx;
    for (idx = 1; idx <= n; idx++) tab[0][idx] = par[idx];
    for (stp = 1; (1 << stp) < n; stp++)
      for (int idx = 1; idx <= n; idx++)
        if (tab[stp - 1][idx] == -1)
          tab[stp][idx] = -1;
        else
          tab[stp][idx] = tab[stp - 1][tab[stp - 1][idx]];
    stp--;
  }
  int go(int cur, int gap, int pos) {
    if (!gap) return cur;
    if (gap & 1) return go(tab[pos][cur], gap / 2, pos + 1);
    return go(cur, gap / 2, pos + 1);
  }
  int LCA(int u, int v) {
    if (lev[u] > lev[v]) swap(u, v);
    v = go(v, lev[v] - lev[u], 0);
    if (u == v) return v;
    int i;
    for (i = stp; i >= 0; i--)
      if (tab[i][u] != tab[i][v]) u = tab[i][u], v = tab[i][v];
    assert(tab[0][u] > 0);
    return tab[0][u];
  }
  void dfs(int idx, int p, int lv) {
    lev[idx] = lv;
    par[idx] = p;
    for (auto x : edge[idx])
      if (x == p)
        continue;
      else
        dfs(x, idx, lv + 1);
  }
  int get_dist(int u, int v) {
    int _lca = LCA(u, v);
    return d[u] + d[v] - 2 * d[_lca];
  }
  void generate_st(int rt) {
    memset(d, -1, sizeof(d));
    bfs(rt);
    dfs(rt, -1, 0);
    init_st(n);
  }
} ug;
int par[100001 + 5], n;
bool flag = false;
void init(int n) {
  for (int i = 1; i <= n; i++) par[i] = i;
}
int find_par(int idx) {
  if (par[idx] == idx) return idx;
  return par[idx] = find_par(par[idx]);
}
void join(int u, int v) {
  int pu = find_par(u);
  int pv = find_par(v);
  if (pu == pv) {
    flag = true;
    return;
  }
  par[pu] = pv;
  return;
}
bool vis[100001 + 5];
vector<int> farthest[100001 + 5];
map<pair<int, int>, int> M;
int dp[100001 << 4], glb;
int F(int u, int v, int stt) {
  int i_stt = stt;
  int ret = 0;
  for (int i = 0; i < (int)dg.edge[v].size(); i++) {
    int x = dg.edge[v][i];
    stt = dg.indx[v][i];
    if (x == u)
      continue;
    else
      ret = max(ret, 1 + F(v, x, stt));
  }
  for (int i = 0; i < (int)ug.edge[v].size(); i++) {
    int x = ug.edge[v][i];
    stt = ug.indx[v][i];
    if (x == u || x == n + 1)
      continue;
    else
      ret = max(ret, 1 + F(v, x, stt));
  }
  return ret;
  return dp[i_stt] = ret;
}
int main() {
  int i, j, k, u, v, w, m;
  scanf("%d %d", &n, &m);
  init(n);
  ug = undirected_graph(n + 1);
  dg = directed_graph(n);
  cmpg = directed_graph(n);
  for (i = 1; i <= m; i++) {
    scanf("%d %d %d", &u, &v, &w);
    if (w == 1) dg.addEdge(u, v);
    if (w == 2) {
      ug.addEdge(u, v);
      join(u, v);
    }
  }
  for (i = 1; i <= n; i++)
    for (auto x : dg.edge[i]) cmpg.addEdge(find_par(i), find_par(x));
  if (flag || dg.hasCycle() || cmpg.hasCycle()) {
    puts("Infinite");
    return 0;
  }
  for (i = 1; i <= n; i++) {
    int p = find_par(i);
    if (vis[p]) continue;
    vis[p] = true;
    int x = ug.bfs(p);
    int y = ug.bfs(x);
    farthest[p].push_back(x);
    if (x != y) farthest[p].push_back(y);
  }
  memset(vis, 0, sizeof(vis));
  for (i = 1; i <= n; i++) {
    int p = find_par(i);
    if (vis[p]) continue;
    vis[p] = true;
    ug.addEdge(n + 1, p);
  }
  memset(dp, -1, sizeof(dp));
  ug.generate_st(n + 1);
  int ans = 0;
  for (i = 1; i <= n; i++) ans = max(ans, F(n + 1, i, counter + i));
  cout << ans << endl;
  return 0;
}
