#include <bits/stdc++.h>
using namespace std;
struct edge {
  int u, v;
  bool f;
  long long g, s;
} e[50010], E[50010], t[50010];
int n, m, cnt, tot, tree;
int p[210];
long long G, S, g, s, ans = 4e18;
int getfa(int u) { return p[u] == u ? u : p[u] = getfa(p[u]); }
void merge(int u, int v) { p[getfa(u)] = getfa(v); }
inline bool cmp_g(edge x, edge y) { return x.g < y.g; }
inline bool cmp_s(edge x, edge y) { return x.s < y.s; }
int main() {
  int i, j;
  scanf("%d%d%I64d%I64d", &n, &m, &G, &S);
  for (i = 1; i <= n; i++) p[i] = i;
  for (i = 1; i <= m; i++)
    scanf("%d%d%I64d%I64d", &e[i].u, &e[i].v, &e[i].g, &e[i].s);
  sort(e + 1, e + 1 + m, cmp_g);
  for (i = 1; i <= m; i++) {
    E[++cnt] = e[i];
    sort(E + 1, E + 1 + cnt, cmp_s);
    tree = n;
    for (j = 1; j <= n; j++) p[j] = j;
    for (j = 1; j <= cnt; j++) E[j].f = 0;
    for (j = 1; j <= cnt && tree > 1; j++)
      if (getfa(E[j].u) != getfa(E[j].v)) {
        s = E[j].s;
        merge(E[j].u, E[j].v);
        E[j].f = 1;
        tree--;
      }
    g = e[i].g;
    if (tree == 1) ans = min(ans, S * s + G * g);
    tot = 0;
    for (j = 1; j <= cnt; j++)
      if (E[j].f) t[++tot] = E[j];
    for (j = 1; j <= tot; j++) E[j] = t[j];
    cnt = tot;
  }
  if (ans == 4e18) ans = -1;
  printf("%I64d\n", ans);
  return 0;
}
