#include <bits/stdc++.h>
using namespace std;
const int oo = 0x3f3f3f3f;
const double eps = 1e-9;
long long gcd(long long a, long long b) { return (b == 0) ? a : gcd(b, a % b); }
struct Frac {
  long long a, b;
  Frac(long long aa = 0, long long bb = 1) {
    if (bb < 0) {
      aa = -aa;
      bb = -bb;
    }
    long long g = gcd(abs(aa), bb);
    a = aa / g;
    b = bb / g;
  }
  Frac& operator=(const Frac& f) {
    a = f.a;
    b = f.b;
    return *this;
  }
  Frac& operator+=(const Frac& f) {
    return *this = Frac(a * f.b + b * f.a, b * f.b);
  }
  Frac& operator-=(const Frac& f) {
    return *this = Frac(a * f.b - b * f.a, b * f.b);
  }
  Frac& operator*=(const Frac& f) { return *this = Frac(a * f.a, b * f.b); }
  Frac& operator/=(const Frac& f) { return *this = Frac(a * f.b, b * f.a); }
  Frac operator-() const { return Frac(-a, b); }
  Frac operator+(const Frac& f) const { return Frac(*this) += f; }
  Frac operator-(const Frac& f) const { return Frac(*this) -= f; }
  Frac operator*(const Frac& f) const { return Frac(*this) *= f; }
  Frac operator/(const Frac& f) const { return Frac(*this) /= f; }
  bool operator<(const Frac& f) const { return a * f.b < b * f.a; }
  bool operator>(const Frac& f) const { return f < *this; }
  bool operator<=(const Frac& f) const { return !(f < *this); }
  bool operator>=(const Frac& f) const { return !(*this < f); }
  bool operator==(const Frac& f) const { return !(*this < f) && !(f < *this); }
  bool operator!=(const Frac& f) const { return !(*this == f); }
};
std::ostream& operator<<(std::ostream& os, const Frac& f) {
  return os << f.a << "/" << f.b;
}
Frac MAX_T = Frac(200000);
struct Event {
  int from, to;
  Frac time_from, time_to;
  long long V;
  Event(int from, int to, Frac time_from, Frac time_to, long long V)
      : from(from), to(to), time_from(time_from), time_to(time_to), V(V) {
    if (this->time_from > this->time_to) {
      swap(this->from, this->to);
      swap(this->time_from, this->time_to);
    }
    if ((this->from < this->to) ^ (this->V > 0)) this->V *= -1;
    assert(this->time_from <= this->time_to);
  }
  ostream& output_me(ostream& os) const {
    return os << from << " -> " << to << " t0=" << time_from
              << " t1=" << time_to << " V=" << V;
  }
  Frac getPoint(Frac c_time) const {
    Frac dif = c_time - time_from;
    Frac pos = Frac(from) + Frac(V) * dif;
    return pos;
  }
};
std::ostream& operator<<(std::ostream& os, const Event& e) {
  return e.output_me(os);
}
const int MAXN = 100100;
vector<int> adj[MAXN];
int depth[MAXN];
int parent[MAXN];
int subsize[MAXN];
int largest[MAXN];
int leader[MAXN];
vector<int> decomposition[MAXN];
vector<Event> events[MAXN];
int lca(int a, int b) {
  while (true) {
    if (leader[a] == leader[b]) return ((depth[a] < depth[b]) ? a : b);
    if (depth[leader[a]] > depth[leader[b]]) swap(a, b);
    b = parent[leader[b]];
  }
}
void init1(int n, int p, int d) {
  depth[n] = d;
  parent[n] = p;
  subsize[n] = 1;
  largest[n] = -1;
  for (auto to : adj[n])
    if (to != p) {
      init1(to, n, d + 1);
      subsize[n] += subsize[to];
      if (largest[n] == -1 || subsize[to] > subsize[largest[n]]) {
        largest[n] = to;
      }
    }
}
void init2(int n, int l) {
  leader[n] = l;
  decomposition[l].push_back(n);
  if (largest[n] != -1) init2(largest[n], l);
  for (auto to : adj[n])
    if (to != parent[n] && to != largest[n]) {
      decomposition[to].push_back(n);
      init2(to, to);
    }
}
bool insert(Frac start_t, int f, int r, int V) {
  if (f == r) return false;
  if (leader[f] == leader[r]) {
    events[leader[f]].push_back(Event(depth[f], depth[r], start_t,
                                      start_t + Frac(depth[f] - depth[r], V),
                                      (V)));
    return true;
  }
  assert(decomposition[leader[f]][0] != leader[f]);
  int m = decomposition[leader[f]][0];
  Frac t_m = Frac(depth[f] - depth[m], V) + start_t;
  events[leader[f]].push_back(Event(depth[f], depth[m], start_t, t_m, (V)));
  return insert(t_m, m, r, V);
}
Frac cur_time;
bool operator<(const Event& a, const Event& b) {
  assert(a.time_from <= cur_time);
  assert(a.time_to >= cur_time);
  assert(b.time_from <= cur_time);
  assert(b.time_to >= cur_time);
  return a.getPoint(cur_time) < b.getPoint(cur_time);
}
bool operator==(const Event& a, const Event& b) {
  assert(a.time_from <= cur_time);
  assert(a.time_to >= cur_time);
  assert(b.time_from <= cur_time);
  assert(b.time_to >= cur_time);
  return a.getPoint(cur_time) == b.getPoint(cur_time);
}
Frac split_(const Event& a, const Event& b) {
  Frac T1 = a.time_from;
  if (T1 < b.time_from) T1 = b.time_from;
  Frac T2 = a.time_to;
  if (T2 > b.time_to) T2 = b.time_to;
  Frac sa = a.getPoint(T1), sb = b.getPoint(T1);
  Frac ea = a.getPoint(T2), eb = b.getPoint(T2);
  if (sa == sb) return T1;
  if (ea == eb) return T2;
  if ((sa < sb) ^ (ea < eb)) {
    Frac d1 = sa - sb;
    Frac d2 = eb - ea;
    d2 = (d2 / d1);
    d1 = Frac(1);
    Frac rel = d1 / (d1 + d2);
    Frac res = (T2 - T1) * rel + T1;
    return res;
  }
  return MAX_T;
}
int main() {
  int N, Q;
  scanf("%d%d", &N, &Q);
  for (int i = (0); i < (N); i++) adj[i].clear();
  for (int i = (0); i < (N); i++) decomposition[i].clear();
  for (int i = (1); i < (N); i++) {
    int a, b;
    scanf("%d%d", &a, &b);
    adj[--a].push_back(--b);
    adj[b].push_back(a);
  }
  memset(leader, -1, sizeof(leader));
  init1(0, 0, 0);
  init2(0, 0);
  for (int q = (0); q < (Q); q++) {
    int T, V, a, b;
    scanf("%d%d%d%d", &T, &V, &a, &b);
    --a;
    --b;
    int r = lca(a, b);
    Frac t_start(T);
    Frac t_end = t_start + Frac(depth[a] + depth[b] - 2 * depth[r], V);
    bool lca_done = insert(t_start, a, r, V);
    lca_done |= insert(t_end, b, r, -V);
    if (!lca_done) {
      Frac t_mid = t_start + Frac(depth[a] - depth[r], V);
      events[leader[r]].push_back(Event(depth[r], depth[r], t_mid, t_mid, 1));
    }
  }
  Frac split = MAX_T;
  for (int ii = (0); ii < (N); ii++) {
    vector<Event>& ev = events[ii];
    if (int((ev).size()) == 0) continue;
    set<Event> active;
    set<tuple<Frac, bool, int> > change;
    for (int i = (0); i < (int((ev).size())); i++) {
      change.insert(make_tuple(ev[i].time_from, 0, i));
      change.insert(make_tuple(ev[i].time_to, 1, i));
    }
    for (auto tpl : change) {
      int id;
      bool remove;
      tie(cur_time, remove, id) = tpl;
      if (split <= cur_time) break;
      if (remove) {
        auto it = active.find(ev[id]);
        if (it != active.begin()) {
          auto it1 = it;
          it1--;
          auto it2 = it;
          it2++;
          if (it2 != active.end()) {
            Frac sp = split_(*it1, *it2);
            if (sp < split) split = sp;
          }
        }
        active.erase(it);
      } else {
        auto it = active.find(ev[id]);
        if (it != active.end()) {
          split = cur_time;
          break;
        }
        active.insert(ev[id]);
        it = active.find(ev[id]);
        if (it != active.begin()) {
          auto pr = it;
          pr--;
          Frac sp = split_(*pr, *it);
          if (sp < split) split = sp;
        }
        auto ne = it;
        ne++;
        if (ne != active.end()) {
          Frac sp = split_(*ne, *it);
          if (sp < split) split = sp;
        }
      }
    }
  }
  if (MAX_T == split)
    printf("-1\n");
  else
    printf("%.10lf\n", split.a / (double)split.b);
  return 0;
}
