#include <bits/stdc++.h>
using namespace std;
const int N = 75, M = 17, inf = 0x3f3f3f3f;
int read() {
  int f = 1, g = 0;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar())
    if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) g = g * 10 + ch - '0';
  return f * g;
}
int n, m, cnt, bel[N], h[N], size[N], dist[N << M], lena, lenb, ans[N];
struct link {
  int pre[N << M], nex[N << M], tail;
  bool h[N << M];
  bool empty() {
    if ((tail == 0) && (nex[0] != 0)) {
      printf("tail=0 head!=0 %d %d\n", nex[0], nex[nex[0]]);
      exit(0);
    }
    if ((tail != 0) && (nex[0] == 0)) {
      printf("tail!=0 head=0 %d %d\n", tail, pre[tail]);
      exit(0);
    }
    return tail == 0;
  }
  void push_back(int x) {
    nex[tail] = x;
    pre[x] = tail;
    nex[x] = 0;
    pre[0] = x;
    tail = x;
  }
  void erase(int x) {
    if (x == 0) {
      puts("???????????????????????????????");
      exit(0);
    }
    nex[pre[x]] = nex[x];
    pre[nex[x]] = pre[x];
    if (x == tail) tail = pre[x];
    nex[x] = pre[x] = inf;
  }
  int head() { return nex[0]; }
} f;
vector<int> ea[N], eb[N], que;
void check(int x, int k, int d, int len) {
  int i = k * n + x;
  if (dist[i] != 0x3f3f3f3f) f.erase(i);
  if (len == lena)
    que.push_back(i);
  else {
    f.push_back(i);
  }
  dist[i] = d + len;
}
void dfs(int x, int fa) {
  bel[x] = fa;
  size[fa]++;
  for (auto y : ea[x])
    if (!bel[y]) dfs(y, fa);
}
int main() {
  n = read();
  m = read();
  lena = read();
  lenb = read();
  for (int i = 1; i <= m; i++) {
    int u = read(), v = read(), w = read();
    if (w == lena) {
      ea[u].push_back(v);
      ea[v].push_back(u);
    } else {
      eb[u].push_back(v);
      eb[v].push_back(u);
    }
  }
  for (int i = 1; i <= n; i++)
    if (!bel[i]) {
      dfs(i, i);
      if (size[i] > 3)
        h[i] = cnt++;
      else
        h[i] = n + i;
    }
  for (int i = 1; i <= n; i++) bel[i] = h[bel[i]];
  memset(dist, 0x3f, sizeof(dist));
  if (bel[1] <= n) {
    que.push_back((n << bel[1]) + 1);
    dist[(n << bel[1]) + 1] = 0;
  } else {
    que.push_back(1);
    dist[1] = 0;
  }
  for (int l = 0; l < que.size(); l++) {
    int i = que[l], x = (i - 1) % n + 1, k = (i - 1) / n;
    while ((!f.empty()) && (dist[f.head()] <= dist[i] + lena)) {
      que.push_back(f.head());
      f.erase(f.head());
      if ((int)que.size() > (n << cnt)) {
        int t = que.back();
        printf("%d %d\n", (t - 1) % n + 1, (t - 1) / n);
        printf("%d\n", dist[t]);
        printf("%d\n", cnt);
        printf("%d %d\n", f.nex[0], f.tail);
        return 9;
      }
    }
    for (auto y : ea[x])
      if (dist[n * k + y] > dist[i] + lena) check(y, k, dist[i], lena);
    for (auto y : eb[x])
      if ((bel[x] != bel[y]) && ((bel[y] > n) || ((k & (1 << bel[y])) == 0))) {
        int t = (bel[y] > n) ? k : (k | (1 << bel[y]));
        if (dist[n * t + y] > dist[i] + lenb) check(y, t, dist[i], lenb);
      }
    if ((l == que.size() - 1) && (!f.empty())) {
      que.push_back(f.head());
      f.erase(f.head());
    }
  }
  for (int i = 1; i <= n; i++) {
    ans[i] = 0x3f3f3f3f;
    for (int k = 0; k < (1 << cnt); k++) ans[i] = min(ans[i], dist[k * n + i]);
    printf("%d ", ans[i]);
  }
  printf("\n");
  return 0;
}
