#include <bits/stdc++.h>
using namespace std;
class dj_set {
  vector<long long> p, rank;

 public:
  dj_set(long long n);
  void unite(long long x, long long y);
  long long find_set(long long x);
};
dj_set::dj_set(long long n) {
  p.resize(n);
  rank.resize(n);
  for (long long i = 0; i < n; i++) p[i] = i;
}
long long dj_set::find_set(long long x) {
  if (p[x] == x) return x;
  return p[x] = find_set(p[x]);
}
void dj_set::unite(long long x, long long y) {
  x = find_set(x);
  y = find_set(y);
  if (rank[x] > rank[y])
    p[y] = x;
  else {
    p[x] = y;
    if (rank[x] == rank[y]) rank[y]++;
  }
}
struct edge {
  long long u, v, g, s;
};
bool operator<(edge a, edge b) {
  return a.g < b.g || (a.g == b.g && a.s < b.s);
}
vector<edge> el;
vector<bool> used;
const long long inf = 5000000000000000000ll;
long long mb = inf, g, s, n;
vector<set<long long> > gd;
long long ng = 0, ns = 0;
stack<int> st;
set<pair<long long, long long>, greater<pair<long long, long long> > > ms;
enum color { black, gray, white };
vector<color> c;
bool dfs_dms(long long u, long long px, long long& msx, bool fst = false) {
  if (fst) {
    c.clear();
    c.resize(n, white);
    while (!st.empty()) st.pop();
  }
  c[u] = gray;
  for (set<long long>::iterator i = gd[u].begin(); i != gd[u].end(); i++) {
    long long v = el[*i].u == u ? el[*i].v : el[*i].u;
    if (c[v] == white) {
      st.push(*i);
      if (!dfs_dms(v, *i, msx)) {
        if (el[msx].s < el[*i].s) msx = *i;
        return false;
      }
      st.pop();
    } else if (c[v] == gray && (st.size() == 0 || *i != px)) {
      msx = *i;
      return false;
    }
  }
  c[u] = black;
  return true;
}
void update_gs() { ns = ms.begin()->first; }
bool g_sv(dj_set& d) {
  long long x = d.find_set(0);
  for (long long i = 1; i < n; i++)
    if (x != d.find_set(i)) return false;
  return true;
}
void add_edge(long long x, dj_set& d) {
  if (d.find_set(el[x].u) != d.find_set(el[x].v)) {
    used[x] = true;
    gd[el[x].u].insert(x);
    gd[el[x].v].insert(x);
    ng = max(ng, el[x].g);
    ms.insert(make_pair(el[x].s, x));
    update_gs();
    d.unite(el[x].u, el[x].v);
  } else {
    used[x] = true;
    gd[el[x].u].insert(x);
    gd[el[x].v].insert(x);
    ms.insert(make_pair(el[x].s, x));
    long long msx = -1;
    dfs_dms(el[x].u, -1, msx, true);
    ms.erase(make_pair(el[msx].s, msx));
    used[msx] = false;
    gd[el[msx].u].erase(msx);
    gd[el[msx].v].erase(msx);
    ng = max(ng, el[x].g);
    update_gs();
  }
  if (g_sv(d)) mb = min(mb, ng * g + ns * s);
}
void kruskal() {
  dj_set d(n);
  gd.resize(n);
  used.resize(el.size());
  for (long long i = 0; i < el.size(); i++) add_edge(i, d);
}
int main() {
  long long m;
  cin >> n >> m;
  cin >> g >> s;
  el.resize(m);
  for (long long i = 0; i < m; i++) {
    cin >> el[i].u >> el[i].v >> el[i].g >> el[i].s;
    el[i].u--;
    el[i].v--;
  }
  sort(el.begin(), el.end());
  kruskal();
  cout << (mb == inf ? -1 : mb) << '\n';
  return 0;
}
