#include <bits/stdc++.h>
#define GET_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,NAME,...) NAME
#define pr(...) cerr<< GET_MACRO(__VA_ARGS__,pr8,pr7,pr6,pr5,pr4,pr3,pr2,pr1)(__VA_ARGS__) <<endl
#define pr1(a) (#a)<<"="<<(a)<<" "
#define pr2(a,b) pr1(a)<<pr1(b)
#define pr3(a,b,c) pr1(a)<<pr2(b,c)
#define pr4(a,b,c,d) pr1(a)<<pr3(b,c,d)
#define pr5(a,b,c,d,e) pr1(a)<<pr4(b,c,d,e)
#define pr6(a,b,c,d,e,f) pr1(a)<<pr5(b,c,d,e,f)
#define pr7(a,b,c,d,e,f,g) pr1(a)<<pr6(b,c,d,e,f,g)
#define pr8(a,b,c,d,e,f,g,h) pr1(a)<<pr7(b,c,d,e,f,g,h)
#define prArr(a) {cerr<<(#a)<<"={";int i=0;for(auto t:(a))cerr<<(i++?", ":"")<<t;cerr<<"}"<<endl;}
using namespace std;
using Int = long long;
using _int = int;
using ll = long long;
using Double = long double;
const Int INF = (1LL<<60)+1e9; // ~ 1.15 * 1e18
const Int mod = (1e9)+7;
const Double EPS = 1e-8;
const Double PI = 6.0 * asin((Double)0.5);
using P = pair<Int,Int>;
template<class T> T Max(T &a,T b){return a=max(a,b);}
template<class T> T Min(T &a,T b){return a=min(a,b);}
template<class T1, class T2> ostream& operator<<(ostream& o,pair<T1,T2> p){return o<<"("<<p.first<<","<<p.second<<")";}
template<class T1, class T2, class T3> ostream& operator<<(ostream& o,tuple<T1,T2,T3> t){
  return o<<"("<<get<0>(t)<<","<<get<1>(t)<<","<<get<2>(t)<<")";}
template<class T1, class T2> istream& operator>>(istream& i,pair<T1,T2> &p){return i>>p.first>>p.second;}
template<class T> ostream& operator<<(ostream& o,vector<T> a){Int i=0;for(T t:a)o<<(i++?" ":"")<<t;return o;}
template<class T> istream& operator>>(istream& i,vector<T> &a){for(T &t:a)i>>t;return i;}
//INSERT ABOVE HERE
class TreeParent{
public:
  Int V;                        //ノード数
  Int root;                     //根
  vector<vector<Int> > G;       //Graph
  vector<Int> parent;           //親
  Int ok;
  TreeParent():V(-1){};
  TreeParent(Int V,Int root = 0):V(V),root(root),G(V),parent(V),ok(0){}
  TreeParent(vector<vector<Int> > G,Int root = 0):V(G.size()),root(root),G(G),parent(V),ok(0){}
  void resize(Int n){*this = TreeParent(n);}
  void add_edge(Int a,Int b){
    ok = false;
    assert(a < V && b < V);
    assert(a >= 0 && b >= 0);
    G[a].push_back(b);
    G[b].push_back(a);
  }
  void build(Int root = -1){
    ok = 1;
    if(root != -1) this->root = root;
    function<void(Int,Int)> dfs = [&](Int pos,Int pre){
      parent[pos] = pre;
      for(Int to:G[pos]) if(to != pre) dfs(to, pos);
    };
    dfs(this->root, -1);
  }
  Int get(Int u){assert(ok); assert(0 <= u && u < V); return parent[u];}

};

Int N, T;
vector<vector<P> > G;
TreeParent parS, parE;
vector<Int> edge;

Int valid = 1;
void dfs(Int pos, Int pre, Int start, TreeParent &par){

  for(P p:G[pos]){
    Int to, i; tie(to, i) = p;
    if(to == pre || par.get(pos) == to) continue;
    dfs(to, pos, 0, par);
  }

  sort(G[pos].begin(), G[pos].end(), [&](auto a, auto b)
       {return edge[a.second] < edge[b.second];});

  Int sum = start==1? 0:T;
  for(P p:G[pos]){
    Int to, i; tie(to, i) = p;
    if(to == pre || par.get(pos) == to) continue;
    valid &= edge[i] - sum > 0; //帰ってこれるか判定
    sum += T;
  }

  for(auto p:G[pos]){
    Int to, i; tie(to, i) = p;
    edge[i] -= sum;
  }
}

void dfs2(Int pos, Int pre, Int flag, TreeParent &par){ //SからEにいく
  Int sum = T;
  if(par.get(pos) != -1){ //pos != E
    for(P p:G[pos]){
      Int to, i; tie(to, i) = p;
      if(to == pre || par.get(pos) == to) continue; //最初に分かれ道にいく
      dfs2(to, pos, 0, par);
    }

    sort(G[pos].begin(), G[pos].end(), [&](auto a, auto b){return edge[a.second] < edge[b.second];});
    for(P p:G[pos]){
      Int to, i; tie(to, i) = p;
      if(to == pre || par.get(pos) == to) continue; //最初に分かれ道にいく
      valid &= edge[i] - sum > 0; //帰ってこれるか判定
      sum += T;
    }

    for(P p:G[pos]){
      Int to, i; tie(to, i) = p;
      if(to == pre || par.get(pos) != to) continue; //Eの方向にいく
      dfs2(to, pos,1, par);
      valid &= edge[i] - sum > 0;
      sum += T;
    }
  }

  if(flag == 0){
    for(auto p:G[pos]){
      Int to, i; tie(to, i) = p;
      edge[i] -= sum;
    }
  }
}

signed main(){
  srand((unsigned)time(NULL));
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  Int S, E;
  cin>>N>>T>>S>>E; S--, E--;

  G.resize(N);
  parS = TreeParent(N, S);
  parE = TreeParent(N, E);
  edge.resize(N-1);
  for(Int i=0;i<N-1;i++){
    Int a, b, w;
    cin>>a>>b>>w; a--, b--;
    G[a].push_back(P(b, i));
    G[b].push_back(P(a, i));
    parS.add_edge(a, b);
    parE.add_edge(a, b);
    edge[i] = w;
  }

  parS.build(); parE.build();

  if(S == E){
    dfs(S, -1, 1, parE);
    cout<<(valid? "Yes":"No")<<endl;
    return 0;
  }

  dfs(S, -1, 1, parE);

  for(auto p:G[S]){
    Int to, i; tie(to, i) = p;
    if(to == parE.get(S)) valid &= edge[i] > 0;
  }
  dfs2(parE.get(S), S, 1, parE);
  dfs(E, -1, 1, parS);

  cout<<(valid? "Yes":"No")<<endl;



  return 0;
}



Measured memory_bytes: 27740