#include <bits/stdc++.h>
using namespace std;
int n, m, nxtmask, a, b, t;
int u, v, w, ans;
const int INF = 2e9 + 5;
struct node {
  int dis, id, mask;
  bool operator<(const node& a) const { return dis > a.dis; }
};
priority_queue<node> Q;
const int maxn = 72;
int num[maxn], f[maxn], id[maxn];
int d[maxn][1 << 17];
vector<pair<int, int> > G[maxn];
void init() {
  for (int i = 1; i <= n; i++) num[i] = 1, f[i] = i, id[i] = -1;
  memset(d, 0x3f3f3f, sizeof(d));
}
int get(int w) {
  if (f[w] == w) return w;
  return f[w] = get(f[w]);
}
void dijkstra() {
  Q.push({0, 1, id[1] != -1 ? (1 << id[1]) : 0});
  d[1][id[1] != -1 ? (1 << id[1]) : 0] = 0;
  while (!Q.empty()) {
    node u = Q.top();
    Q.pop();
    if (u.dis > d[u.id][u.mask]) continue;
    for (auto i : G[u.id]) {
      if (id[i.first] != -1 && ((1 << id[i.first]) & u.mask) &&
          id[u.id] != id[i.first])
        continue;
      if (get(u.id) == get(i.first) && i.second == b) continue;
      if (id[i.first] == -1)
        nxtmask = u.mask;
      else
        nxtmask = u.mask | (1 << id[i.first]);
      if (d[i.first][nxtmask] > u.dis + i.second) {
        d[i.first][nxtmask] = u.dis + i.second;
        Q.push({u.dis + i.second, i.first, nxtmask});
      }
    }
  }
}
int main() {
  cin >> n >> m >> a >> b;
  init();
  for (int i = 1; i <= m; i++) {
    cin >> u >> v >> w;
    G[u].push_back({v, w});
    G[v].push_back({u, w});
    if (w == a) {
      get(u);
      get(v);
      if (f[u] != f[v]) {
        num[f[u]] += num[f[v]];
        f[f[v]] = f[u];
      }
    }
  }
  for (int i = 1; i <= n; i++) {
    if (num[get(i)] <= 3) continue;
    if (id[get(i)] == -1) id[get(i)] = t++;
    id[i] = id[get(i)];
  }
  dijkstra();
  for (int i = 1; i <= n; i++) {
    ans = INF;
    for (int j = 0; j < 1 << t; j++) {
      ans = min(ans, d[i][j]);
    }
    cout << ans << ' ';
  }
}
