#include <bits/stdc++.h>
using namespace std;
int dis[75][1 << 18];
bool mark[75][1 << 18];
int n, m, A, B;
vector<pair<int, int> > ve[75];
struct zzt {
  pair<int, int> to;
  int di;
};
bool operator<(zzt aa, zzt bb) { return aa.di > bb.di; }
priority_queue<zzt> q;
int fa[75];
int gf(int x) { return fa[x] == x ? x : fa[x] = gf(fa[x]); }
int sz[75];
void merge(int x, int y) {
  x = gf(x);
  y = gf(y);
  if (x != y) fa[x] = y, sz[y] += sz[x];
}
int mk[75], mkid;
int ozt(int x) { return mk[x] ? (1 << (mk[x] - 1)) : 0; }
int main() {
  scanf("%d%d%d%d", &n, &m, &A, &B);
  for (int i = 1; i <= n; i++) fa[i] = i, sz[i] = 1;
  for (int i = 1; i <= m; i++) {
    int x, y, z;
    scanf("%d%d%d", &x, &y, &z);
    ve[x].push_back(pair<int, int>(y, z));
    ve[y].push_back(pair<int, int>(x, z));
    if (z == A) merge(x, y);
  }
  mkid = 0;
  for (int i = 1; i <= n; i++) {
    if ((!mk[i]) && sz[gf(i)] > 3) {
      ++mkid;
      for (int j = i; j <= n; j++) {
        if (gf(j) == gf(i)) mk[j] = mkid;
      }
    }
  }
  q.push((zzt){pair<int, int>(1, ozt(1)), 0});
  memset(dis, 0x3f, sizeof dis);
  dis[1][ozt(1)] = 0;
  while (q.size()) {
    int x = q.top().to.first;
    int zt = q.top().to.second;
    q.pop();
    if (mark[x][zt]) continue;
    mark[x][zt] = 1;
    for (auto p : ve[x]) {
      int y = p.first;
      int le = p.second;
      if (le == A) {
        if (dis[y][zt] > dis[x][zt] + le) {
          dis[y][zt] = dis[x][zt] + le;
          q.push((zzt){pair<int, int>(y, zt), dis[y][zt]});
        }
      } else if (gf(y) != gf(x) && (ozt(y) & zt) == 0) {
        if (dis[y][zt | ozt(y)] > dis[x][zt] + le) {
          dis[y][zt | ozt(y)] = dis[x][zt] + le;
          q.push((zzt){pair<int, int>(y, zt | ozt(y)), dis[y][zt | ozt(y)]});
        }
      }
    }
  }
  for (int i = 1; i <= n; i++) {
    int ans = 0x3f3f3f3f;
    for (int j = 0; j <= (1 << mkid) - 1; j++) {
      ans = min(ans, dis[i][j]);
    }
    cout << ans << ' ';
  }
}
