#include <bits/stdc++.h>
using namespace std;
const long long MAXN = 200;
const long long MAXM = 50 * 1000;
long long N, M;
long long G, S;
long long parent[MAXN];
long long siz[MAXN];
multiset<long long> minSilver[MAXN];
long long mSilver;
bool haveANS;
pair<pair<long long, long long>, pair<long long, long long> > e[MAXM];
bool cmp(pair<pair<long long, long long>, pair<long long, long long> > a,
         pair<pair<long long, long long>, pair<long long, long long> > b) {
  return a.second.first < b.second.first;
}
struct comp {
  bool operator()(long long a, long long b) {
    if (e[a].second.second != e[b].second.second)
      return e[a].second.second < e[b].second.second;
    return a < b;
  }
};
set<long long, comp> v[MAXN];
long long findpath(long long a) {
  if (a == parent[a]) return a;
  long long b = findpath(parent[a]);
  parent[a] = b;
  return b;
}
bool is[MAXN];
long long dfs(long long a, long long b, long long c) {
  if (is[a]) return -2;
  if (a == b) return -1;
  is[a] = true;
  long long ans = -2, got = -2;
  for (set<long long, comp>::iterator it = v[a].begin(); it != v[a].end();
       ++it) {
    long long f = *it;
    long long nei = e[f].first.first ^ e[f].first.second ^ a;
    long long DFS = dfs(nei, b, c);
    if (DFS == -1) {
      ans = e[f].second.second;
      got = f;
    }
    if (DFS >= 0) {
      if (e[DFS].second.second > ans) {
        ans = e[DFS].second.second;
        got = DFS;
      }
      if (e[f].second.second > ans) {
        ans = e[f].second.second;
        got = f;
      }
    }
  }
  return got;
}
void Add(long long a, long long b) { v[a].insert(b); }
long long Last(multiset<long long>& a) {
  multiset<long long>::iterator it = a.end();
  --it;
  return *it;
}
void Join(long long a, long long b, long long c, long long d) {
  if (a == b) return;
  long long ga = findpath(a);
  long long gb = findpath(b);
  if (ga == gb) {
    memset(is, false, sizeof(is));
    long long ret = dfs(a, b, c);
    if (ret >= 0 && e[ret].second.second > c) {
      v[e[ret].first.first].erase(ret);
      v[e[ret].first.second].erase(ret);
      Add(a, d);
      Add(b, d);
      minSilver[ga].erase(minSilver[ga].find(e[ret].second.second));
      minSilver[ga].insert(c);
    }
    if (siz[ga] == N) {
      mSilver = min(mSilver, Last(minSilver[ga]));
    }
    return;
  }
  if (siz[ga] < siz[gb]) swap(ga, gb);
  parent[gb] = ga;
  siz[ga] += siz[gb];
  Add(a, d);
  Add(b, d);
  for (multiset<long long>::iterator it = minSilver[gb].begin();
       it != minSilver[gb].end(); ++it) {
    minSilver[ga].insert(*it);
  }
  minSilver[ga].insert(c);
  if (siz[ga] == N) {
    haveANS = true;
    mSilver = Last(minSilver[ga]);
  }
}
int main() {
  cin >> N >> M >> G >> S;
  for (long long i = 0; i < M; ++i) {
    cin >> e[i].first.first >> e[i].first.second >> e[i].second.first >>
        e[i].second.second;
    --e[i].first.first, --e[i].first.second;
  }
  sort(e, e + M, cmp);
  for (long long i = 0; i < N; ++i) {
    parent[i] = i;
    siz[i] = 1;
  }
  long long BestAns = -1;
  for (long long i = 0; i < M; ++i) {
    Join(e[i].first.first, e[i].first.second, e[i].second.second, i);
    if (haveANS) {
      long long d = e[i].second.first * G + mSilver * S;
      if (BestAns == -1 || d < BestAns) BestAns = d;
    }
  }
  cout << BestAns << endl;
  return 0;
}
