using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("3 5");
WillReturn.Add("1 2 3");
WillReturn.Add("1 3 2");
//Yes
}
else if (InputPattern == "Input2") {
WillReturn.Add("3 4");
WillReturn.Add("1 2 3");
WillReturn.Add("1 3 2");
//No
}
else if (InputPattern == "Input3") {
WillReturn.Add("10 15");
WillReturn.Add("3 8 3");
WillReturn.Add("5 9 3");
WillReturn.Add("6 7 1");
WillReturn.Add("7 8 1");
WillReturn.Add("2 8 5");
WillReturn.Add("2 4 5");
WillReturn.Add("4 9 3");
WillReturn.Add("1 4 5");
WillReturn.Add("1 10 2");
//Yes
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static long mN;
static long mX;
struct EdgeInfoDef
{
internal long ToNode;
internal long Cost;
}
static Dictionary<long, List<EdgeInfoDef>> mEdgeInfoListDict = new Dictionary<long, List<EdgeInfoDef>>();
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => long.Parse(pX)).ToArray();
SplitAct(InputList[0]);
mN = wkArr[0];
mX = wkArr[1];
foreach (string EachStr in InputList.Skip(1)) {
SplitAct(EachStr);
long A = wkArr[0];
long B = wkArr[1];
long C = wkArr[2];
Action<long, long, long> AddEdgeAct = (pFromNode, pToNode, pCost) =>
{
if (mEdgeInfoListDict.ContainsKey(pFromNode) == false) {
mEdgeInfoListDict[pFromNode] = new List<EdgeInfoDef>();
}
EdgeInfoDef WillAdd;
WillAdd.ToNode = pToNode;
WillAdd.Cost = pCost;
mEdgeInfoListDict[pFromNode].Add(WillAdd);
};
AddEdgeAct(A, B, C);
AddEdgeAct(B, A, C);
}
for (long I = 1; I <= mN; I++) {
bool HasAnswer = ExecBFS(I);
if (HasAnswer) {
Console.WriteLine("Yes");
return;
}
}
Console.WriteLine("No");
}
struct JyoutaiDef
{
internal long CurrNode;
internal long CostSum;
}
static bool ExecBFS(long pStaNode)
{
var Que = new Queue<JyoutaiDef>();
JyoutaiDef WillEnquue;
WillEnquue.CurrNode = pStaNode;
WillEnquue.CostSum = 0;
Que.Enqueue(WillEnquue);
var VisitedSet = new HashSet<long>();
VisitedSet.Add(pStaNode);
while (Que.Count > 0) {
JyoutaiDef Dequeued = Que.Dequeue();
// クリア判定
if (Dequeued.CostSum == mX) {
return true;
}
// 枝切り
if (Dequeued.CostSum > mX) {
continue;
}
if (mEdgeInfoListDict.ContainsKey(Dequeued.CurrNode) == false) {
continue;
}
foreach (EdgeInfoDef EachEdgeInfo in mEdgeInfoListDict[Dequeued.CurrNode]) {
if (VisitedSet.Add(EachEdgeInfo.ToNode) == false) {
continue;
}
WillEnquue.CurrNode = EachEdgeInfo.ToNode;
WillEnquue.CostSum = Dequeued.CostSum + EachEdgeInfo.Cost;
Que.Enqueue(WillEnquue);
}
}
return false;
}
}