#include <bits/stdc++.h>
using namespace std;
void Get(int &T) {
  char C;
  bool F = 0;
  for (; C = getchar(), C < '0' || C > '9';)
    if (C == '-') F = 1;
  for (T = C - '0'; C = getchar(), C >= '0' && C <= '9'; T = T * 10 + C - '0')
    ;
  F && (T = -T);
}
void Get(long long &T) {
  char C;
  bool F = 0;
  for (; C = getchar(), C < '0' || C > '9';)
    if (C == '-') F = 1;
  for (T = C - '0'; C = getchar(), C >= '0' && C <= '9'; T = T * 10 + C - '0')
    ;
  F && (T = -T);
}
int U[50005];
int V[50005];
int W[50005];
int W2[50005];
int Order[50005];
int N, M;
bool Cmp(int X, int Y) { return W2[X] < W2[Y]; }
long long C1, C2;
void Init() {
  Get(N);
  Get(M);
  Get(C1);
  Get(C2);
  for (int i = 1; i <= M; i++) {
    Get(U[i]);
    Get(V[i]);
    Get(W[i]);
    Get(W2[i]);
    Order[i] = i;
  }
  std::sort(Order + 1, Order + M + 1, Cmp);
}
bool Delete[100005];
struct E {
  int V, W, Next;
} Edge[100005];
int EdgeTop = 1;
int Head[205];
void Add(int U, int V, int W) {
  Edge[++EdgeTop] = (E){V, W, Head[U]};
  Head[U] = EdgeTop;
}
int Visited[205];
int Time;
int StackAns[205];
int StackX[205];
int Stacki[205];
multiset<int> Hash;
int DFS(int X, int Y) {
  int Top = 1, i;
  StackX[Top] = X;
Call:
  X = StackX[Top];
  if (X == Y) {
    int Max = StackAns[1];
    for (int i = 2; i < Top; i++) {
      if (Edge[StackAns[i]].W > Edge[Max].W) Max = StackAns[i];
    }
    return Max;
  }
  Visited[X] = Time;
  for (; Delete[Head[X]]; Head[X] = Edge[Head[X]].Next)
    ;
  for (i = Head[X]; i; i = Edge[i].Next) {
    if (Visited[Edge[i].V] != Time) {
      StackAns[Top] = i;
      StackX[Top + 1] = Edge[i].V;
      Stacki[Top] = i;
      Top++;
      goto Call;
    Return:
      Top--;
      X = StackX[Top];
      i = Stacki[Top];
    }
    for (; Delete[Edge[i].Next]; Edge[i].Next = Edge[Edge[i].Next].Next)
      ;
  }
  if (Top >= 2) goto Return;
  return -1;
}
long long Ans;
void Work() {
  Ans = 0x2f2f2f2f2f2f2f2fll;
  for (int k = 1, i; k <= M; k++) {
    i = Order[k];
    if (U[i] == V[i]) continue;
    Time++;
    int Max = DFS(U[i], V[i]);
    if (Max == -1) {
      Hash.insert(W[i]);
      Add(U[i], V[i], W[i]);
      Add(V[i], U[i], W[i]);
    } else if (Edge[Max].W > W[i]) {
      Delete[Max] = Delete[Max ^ 1] = 1;
      Hash.erase(Hash.find(Edge[Max].W));
      Hash.insert(W[i]);
      Add(U[i], V[i], W[i]);
      Add(V[i], U[i], W[i]);
    }
    if (Hash.size() == N - 1) {
      long long Ans0 = *Hash.rbegin() * C1 + W2[i] * C2;
      if (Ans > Ans0) Ans = Ans0;
    }
  }
}
void Output() {
  if (Ans >= 0x2f2f2f2f2f2f2f2fll)
    puts("-1");
  else
    printf("%I64d\n", Ans);
}
int main() {
  Init();
  Work();
  Output();
  return 0;
}
