// base off ecnerwala's solution...
#include <bits/stdc++.h>
using namespace std;
template <int MOD_> struct modnum {
static constexpr int MOD = MOD_;
static_assert(MOD_ > 0, "MOD must be positive");
private:
using ll = long long;
int v;
static int minv(int a, int m) {
a %= m;
assert(a);
return a == 1 ? 1 : int(m - ll(minv(m, a)) * ll(m) / a);
}
public:
modnum() : v(0) {}
modnum(ll v_) : v(int(v_ % MOD)) { if (v < 0) v += MOD; }
explicit operator int() const { return v; }
friend std::ostream& operator << (std::ostream& out, const modnum& n) { return out << int(n); }
friend std::istream& operator >> (std::istream& in, modnum& n) { ll v_; in >> v_; n = modnum(v_); return in; }
friend bool operator == (const modnum& a, const modnum& b) { return a.v == b.v; }
friend bool operator != (const modnum& a, const modnum& b) { return a.v != b.v; }
modnum inv() const {
modnum res;
res.v = minv(v, MOD);
return res;
}
friend modnum inv(const modnum& m) { return m.inv(); }
modnum neg() const {
modnum res;
res.v = v ? MOD-v : 0;
return res;
}
friend modnum neg(const modnum& m) { return m.neg(); }
modnum operator- () const {
return neg();
}
modnum operator+ () const {
return modnum(*this);
}
modnum& operator ++ () {
v ++;
if (v == MOD) v = 0;
return *this;
}
modnum& operator -- () {
if (v == 0) v = MOD;
v --;
return *this;
}
modnum& operator += (const modnum& o) {
v += o.v;
if (v >= MOD) v -= MOD;
return *this;
}
modnum& operator -= (const modnum& o) {
v -= o.v;
if (v < 0) v += MOD;
return *this;
}
modnum& operator *= (const modnum& o) {
v = int(ll(v) * ll(o.v) % MOD);
return *this;
}
modnum& operator /= (const modnum& o) {
return *this *= o.inv();
}
friend modnum operator ++ (modnum& a, int) { modnum r = a; ++a; return r; }
friend modnum operator -- (modnum& a, int) { modnum r = a; --a; return r; }
friend modnum operator + (const modnum& a, const modnum& b) { return modnum(a) += b; }
friend modnum operator - (const modnum& a, const modnum& b) { return modnum(a) -= b; }
friend modnum operator * (const modnum& a, const modnum& b) { return modnum(a) *= b; }
friend modnum operator / (const modnum& a, const modnum& b) { return modnum(a) /= b; }
};
template <typename T> T pow(T a, long long b) {
assert(b >= 0);
T r = 1; while (b) { if (b & 1) r *= a; b >>= 1; a *= a; } return r;
}
using num = modnum<int(1e9) + 7>;
using ll = long long;
struct DSU {
vector<int> par;
DSU() {}
DSU(int n) : par(n, -1) {}
int getpar(int a) {
return par[a] < 0 ? a : (par[a] = getpar(par[a]));
}
bool merge(int a, int b) {
a = getpar(a);
b = getpar(b);
if (a == b) return false;
if (-par[a] < -par[b]) swap(a, b);
par[a] += par[b];
par[b] = a;
return true;
}
};
struct node {
ll a, b, d;
int c, e;
bool is_root;
int root;
int depth;
int idx;
vector<int> ch;
int cyc_len;
ll cyc_offset;
unordered_map<ll, map<ll, int>> cyc_ends;
};
vector<node> nodes;
int main() {
ios::sync_with_stdio(0), cin.tie(0);
int n;
ll x0;
cin >> n >> x0;
nodes.resize(n+1);
for (int i = 0; i < n; i++) {
cin >> nodes[i].a >> nodes[i].b >> nodes[i].c >> nodes[i].d >> nodes[i].e;
nodes[i].c--; nodes[i].e--;
nodes[i].b += nodes[i].a;
}
nodes[n].a = nodes[n].b = nodes[n].d = 0;
nodes[n].c = nodes[n].e = n;
vector<int> roots;
{
DSU dsu(n+1);
for (int i = 0; i <= n; i++) {
if (dsu.merge(i, nodes[i].e)) {
nodes[nodes[i].e].ch.push_back(i);
nodes[i].is_root = false;
} else {
roots.push_back(i);
nodes[i].is_root = true;
}
}
assert(roots.back() == n);
}
unordered_map<ll, map<int, int>> tree_ends;
{
int cur_idx = 0;
for (int root : roots) {
ll cyc_offset = nodes[root].d;
nodes[root].d = 0;
nodes[root].depth = 0;
function<void(int)> dfs = [&](int v) {
nodes[v].root = root;
nodes[v].idx = cur_idx;
nodes[v].a += nodes[v].d;
if (!tree_ends.count(nodes[v].a)) {
tree_ends[nodes[v].a][0] = -1;
}
int old_val = tree_ends[nodes[v].a].rbegin()->second;
assert(cur_idx >= tree_ends[nodes[v].a].rbegin()->first);
tree_ends[nodes[v].a][cur_idx] = v;
cur_idx++;
for (int w : nodes[v].ch) {
nodes[w].d += nodes[v].d;
nodes[w].depth = nodes[v].depth + 1;
dfs(w);
}
assert(cur_idx >= tree_ends[nodes[v].a].rbegin()->first);
tree_ends[nodes[v].a][cur_idx] = old_val; // 退出
};
dfs(root);
cyc_offset += nodes[nodes[root].e].d;
unordered_map<ll, map<ll, int>> cyc_ends;
for (int cur = nodes[root].e; true; cur = nodes[cur].e) {
ll val = nodes[cur].a;
ll mod_val;
if (cyc_offset == 0) {
mod_val = val;
} else if (cyc_offset > 0) {
mod_val = (val % cyc_offset + cyc_offset) % cyc_offset;
} else {
val = -val;
mod_val = (val % -cyc_offset + -cyc_offset) % -cyc_offset;
}
if (!cyc_ends[mod_val].count(val)) {
cyc_ends[mod_val][val] = cur;
}
if (cur == root) break;
}
nodes[root].cyc_len = nodes[nodes[root].e].depth + 1;
nodes[root].cyc_offset = cyc_offset;
nodes[root].cyc_ends = cyc_ends;
}
assert(cur_idx == n+1);
}
int cur = 0;
ll x = x0 + nodes[cur].d;
num ans = 0;
vector<bool> vis(n);
while (cur != n) {
if (x == nodes[cur].a) {
if (vis[cur]) {
cout << -1 << '\n';
exit(0);
}
vis[cur] = true;
x = nodes[cur].b;
cur = nodes[cur].c;
x += nodes[cur].d;
ans++;
} else if (nodes[cur].is_root) {
// x + (mod - D_tgt) + k * mod = A - D_tgt
// x + (k+1) * mod = A
// greater
int cyc_len = nodes[cur].cyc_len;
ll cyc_offset = nodes[cur].cyc_offset;
auto& cyc_ends = nodes[cur].cyc_ends;
if (cyc_offset == 0) {
if (!cyc_ends.count(x)) {
// we're screwed
cout << -1 << '\n';
exit(0);
}
int nxt = cyc_ends[x][x];
ans += cyc_len - nodes[nxt].depth;
cur = nxt;
} else {
ll mod = cyc_offset;
if (mod < 0) {
x = -x;
mod = -mod;
}
ll mod_x = (x % mod + mod) % mod;
if (!cyc_ends.count(mod_x)) {
cout << -1 << '\n';
exit(0);
}
auto& mod_vals = cyc_ends[mod_x];
if (!cyc_ends.count(mod_x)) {
cout << -1 << '\n';
exit(0);
}
auto it = mod_vals.upper_bound(x);
if (it == mod_vals.end()) {
cout << -1 << '\n';
exit(0);
}
int nxt = it->second;
ans += num((cyc_len) * (it->first - x) / mod) - nodes[nxt].depth;
cur = nxt;
}
x = nodes[cur].a;
} else {
int nxt = nodes[cur].root;
if (tree_ends.count(x)) {
auto it = tree_ends[x].upper_bound(nodes[cur].idx);
assert(it != tree_ends[x].begin());
--it;
if (it->second != -1) {
nxt = it->second;
assert(x == nodes[nxt].a);
assert(nodes[nxt].root = nodes[cur].root);
}
}
ans += nodes[cur].depth - nodes[nxt].depth;
cur = nxt;
}
}
cout << ans << '\n';
}