#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
struct edge {
  int from, to;
  int idx;
  edge(int f, int t, int n) : from(f), to(t), idx(n) {}
};
int n, m;
vector<vector<edge>> g;
bool visited[100005];
map<int, map<int, int>> memo;
int dfs(int cur, int par) {
  int ret = 0;
  if (memo.count(cur) and memo[cur].count(par)) return memo[cur][par];
  for (const edge& e : g[cur]) {
    if (e.to == par) continue;
    int tmp = 1 + dfs(e.to, cur);
    ret = max(ret, tmp);
  }
  memo[cur][par] = ret;
  return ret;
}
namespace Yuudachi {
vector<bool> used;
bool dfs(int cur, int last_edge) {
  if (used[cur]) return false;
  used[cur] = true;
  for (const edge& e : g[cur]) {
    if (e.idx == last_edge) continue;
    if (!dfs(e.to, e.idx)) {
      return false;
    }
  }
  used[cur] = false;
  return true;
}
bool poi() {
  used.assign(n, false);
  bool ret = dfs(0, -1);
  return ret;
}
}  // namespace Yuudachi
int main() {
  cin >> n >> m;
  g.resize(n);
  for (int i = 0; i < (m); i++) {
    int x, y, w;
    cin >> x >> y >> w;
    x--;
    y--;
    if (w == 1) {
      g[x].push_back(edge(x, y, i));
    } else {
      g[x].push_back(edge(x, y, i));
      g[y].push_back(edge(y, x, i));
    }
  }
  if (!Yuudachi::poi()) {
    cout << "Infinite" << endl;
    return 0;
  }
  fill(visited, visited + n, false);
  int ans = 0;
  for (int i = 0; i < (n); i++)
    if (!visited[i]) {
      ans = max(ans, dfs(i, i));
    }
  cout << ans << endl;
  return 0;
}
