#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const double inf = 1e10;
const double eps = 1e-10;
int n, m;
int tim, fa[N], dfn[N], dep[N], siz[N], son[N], top[N], vis[N];
double res, ans = inf, c[N], e[N];
struct Line {
  double t, c;
  int u, id, type;
} L[N];
vector<int> G[N];
vector<Line> tmp[N];
multiset<Line> S;
template <typename _Tp>
inline void IN(_Tp& x) {
  char ch;
  bool flag = 0;
  x = 0;
  while (ch = getchar(), !isdigit(ch))
    if (ch == '-') flag = 1;
  while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
  if (flag) x = -x;
}
double end_pos(const Line& t) { return dep[t.u] + (res - t.t) * c[t.id]; }
double end_tim(int u, int v, double c) { return (dep[u] - dep[v]) / c; }
int operator<(const Line& x, const Line& y) { return end_pos(x) < end_pos(y); }
inline void addedge(int u = 0, int v = 0) {
  IN(u), IN(v), G[u].push_back(v), G[v].push_back(u);
}
namespace Tree {
void dfs1(int u, int f) {
  fa[u] = f, dep[u] = dep[f] + 1, siz[u] = 1;
  for (auto v : G[u])
    if (v != f)
      dfs1(v, u), siz[u] += siz[v], son[u] = siz[son[u]] > siz[v] ? son[u] : v;
}
void dfs2(int u, int t) {
  top[u] = t, dfn[u] = ++tim;
  if (son[u]) dfs2(son[u], t);
  for (auto v : G[u])
    if (v != fa[u] && v != son[u]) dfs2(v, v);
}
inline int lca(int u, int v) {
  for (; top[u] != top[v]; u = fa[top[u]])
    if (dep[top[u]] < dep[top[v]]) swap(u, v);
  return dep[u] > dep[v] ? v : u;
}
}  // namespace Tree
using namespace Tree;
inline void update(const Line& x, const Line& y) {
  double v = end_pos(y) - end_pos(x),
         p = fabs(v) < eps ? 0
                           : (end_pos(y) - end_pos(x)) / (c[x.id] - c[y.id]);
  if (p > -eps && p + res < min(e[x.id], e[y.id]) + eps)
    ans = min(ans, p + res);
}
inline void solve(int i) {
  double t, T;
  IN(t), IN(c[i]);
  int x, y, u, v, _lca, flag = 1;
  IN(x), IN(y), u = x, v = y, _lca = lca(u, v), T = t + end_tim(u, _lca, c[i]);
  for (; top[u] ^ top[v]; u = fa[top[u]]) {
    if (dep[top[u]] < dep[top[v]]) swap(u, v), flag ^= 1;
    if (flag)
      tmp[top[u]].push_back((Line){t + end_tim(x, u, c[i]), -c[i], u, i, 1}),
          tmp[top[u]].push_back((Line){t + end_tim(x, fa[top[u]], c[i]), -c[i],
                                       fa[top[u]], i, 0});
    else
      tmp[top[u]].push_back((Line){T + end_tim(u, _lca, c[i]), c[i], x, i, 0}),
          tmp[top[u]].push_back((Line){T + end_tim(fa[top[u]], _lca, c[i]),
                                       c[i], fa[top[u]], i, 1});
  }
  if (dep[u] < dep[v]) swap(u, v), flag ^= 1;
  if (flag)
    tmp[top[u]].push_back((Line){t + end_tim(x, u, c[i]), -c[i], u, i, 1}),
        tmp[top[u]].push_back((Line){T, -c[i], v, i, 0});
  else
    tmp[top[u]].push_back((Line){T, c[i], v, i, 1}),
        tmp[top[u]].push_back((Line){T + end_tim(u, v, c[i]), c[i], u, i, 0});
}
void work(int u) {
  S.clear();
  sort(tmp[u].begin(), tmp[u].end(), [&](const Line& a, const Line& b) {
    return fabs(a.t - b.t) < eps ? a.type > b.type : a.t < b.t;
  });
  for (Line now : tmp[u])
    if (now.type)
      L[now.id] = now;
    else
      e[now.id] = now.t;
  for (Line now : tmp[u]) {
    if ((res = now.t) > ans + eps) break;
    if (now.type) {
      auto it = S.insert(now);
      c[now.id] = now.c;
      if (it != S.begin()) update(now, *prev(it));
      if (++it != S.end()) update(now, *it);
    } else {
      auto it = S.find(L[now.id]);
      if (it != S.begin() && next(it) != S.end()) update(*prev(it), *next(it));
      if (it != S.end()) S.erase(it);
    }
  }
}
int main() {
  IN(n), IN(m);
  for (int i = 2; i <= n; ++i) addedge();
  dfs1(1, 0), dfs2(1, 1);
  for (int i = 1; i <= m; ++i) solve(i);
  for (int i = 1; i <= n; ++i)
    if (!vis[top[i]]) vis[top[i]] = 1, work(top[i]);
  fabs(ans - inf) < eps ? puts("-1") : printf("%.10lf\n", ans);
  return 0;
}
