using System; using System.Collections.Generic; using System.Linq; class Program { static string InputPattern = "InputX"; static List GetInputList() { var WillReturn = new List(); if (InputPattern == "Input1") { WillReturn.Add("3 3 2 19"); WillReturn.Add("1 3 4"); WillReturn.Add("2 3 1"); WillReturn.Add("1 2 5"); WillReturn.Add("2 5"); WillReturn.Add("3 4"); //3 } else { string wkStr; while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr); } return WillReturn; } struct EdgeInfoDef { internal long ToNode; internal long Cost; } static Dictionary> mEdgeInfoListDict = new Dictionary>(); static Dictionary mDEDict = new Dictionary(); static long mY; static void Main() { List InputList = GetInputList(); long[] wkArr = { }; Action SplitAct = pStr => wkArr = pStr.Split(' ').Select(pX => long.Parse(pX)).ToArray(); SplitAct(InputList[0]); long N = wkArr[0]; long M = wkArr[1]; mY = wkArr[3]; foreach (string EachStr in InputList.Skip(1).Take((int)M)) { SplitAct(EachStr); long FromNode = wkArr[0]; long ToNode = wkArr[1]; long Cost = wkArr[2]; Action AddAct = (pNode1, pNode2) => { if (mEdgeInfoListDict.ContainsKey(pNode1) == false) { mEdgeInfoListDict[pNode1] = new List(); } EdgeInfoDef WillAdd; WillAdd.ToNode = pNode2; WillAdd.Cost = Cost; mEdgeInfoListDict[pNode1].Add(WillAdd); }; AddAct(FromNode, ToNode); // 正方向の辺 AddAct(ToNode, FromNode); // 逆方向の辺 } foreach (string EachStr in InputList.Skip(1 + (int)M)) { SplitAct(EachStr); long D = wkArr[0]; long E = wkArr[1]; mDEDict[D] = E; } Dijkstra(1, N); } // ダイクストラ法で、各ノードまでの最短距離を求める static void Dijkstra(long pStaNode, long pGoalNode) { var InsPQueue = new PQueue(); // 距離合計[確定ノード]なDict var KakuteiNodeDict = new Dictionary(); KakuteiNodeDict.Add(pStaNode, 0); //Enqueue処理 Action EnqueueAct = pFromNode => { if (mEdgeInfoListDict.ContainsKey(pFromNode) == false) { return; } foreach (EdgeInfoDef EachEdge in mEdgeInfoListDict[pFromNode]) { // 確定ノードならContinue if (KakuteiNodeDict.ContainsKey(EachEdge.ToNode)) continue; long wkSumCost = KakuteiNodeDict[pFromNode] + EachEdge.Cost; PQueue.PQueueJyoutaiDef WillEnqueue; WillEnqueue.Node = EachEdge.ToNode; WillEnqueue.SumCost = wkSumCost; InsPQueue.Enqueue(WillEnqueue); } }; EnqueueAct(pStaNode); while (InsPQueue.IsEmpty() == false) { PQueue.PQueueJyoutaiDef Dequeued = InsPQueue.Dequeue(); // 確定ノードならcontinue if (KakuteiNodeDict.ContainsKey(Dequeued.Node)) continue; // 枝切り // if (KakuteiNodeDict.ContainsKey(pGoalNode)) break; KakuteiNodeDict.Add(Dequeued.Node, Dequeued.SumCost); EnqueueAct(Dequeued.Node); } var AnswerList = new List(); for (int I = 1; I <= pGoalNode; I++) { if (KakuteiNodeDict.ContainsKey(I)) { //Console.WriteLine(KakuteiNodeDict[I]); if (mDEDict.ContainsKey(I)) { long Rest = mY - KakuteiNodeDict[I]; if (Rest > 0) { AnswerList.Add(Rest/mDEDict[I]); } } } else { //Console.WriteLine(-1); } } if (AnswerList.Count == 0) { Console.WriteLine(0); } else { Console.WriteLine(AnswerList.Max()); } } } #region PQueue // 優先度付きキュー internal class PQueue { internal struct PQueueJyoutaiDef { internal long Node; internal long SumCost; } private Dictionary mHeapDict = new Dictionary(); internal bool IsEmpty() { return mHeapDict.Count == 0; } // エンキュー処理 internal void Enqueue(PQueueJyoutaiDef pAddJyoutai) { long CurrNode = 1 + mHeapDict.Count; mHeapDict[CurrNode] = pAddJyoutai; while (1 < CurrNode && mHeapDict[CurrNode / 2].SumCost > mHeapDict[CurrNode].SumCost) { PQueueJyoutaiDef Swap = mHeapDict[CurrNode]; mHeapDict[CurrNode] = mHeapDict[CurrNode / 2]; mHeapDict[CurrNode / 2] = Swap; CurrNode /= 2; } } // デキュー処理 internal PQueueJyoutaiDef Dequeue() { PQueueJyoutaiDef TopNode = mHeapDict[1]; long LastNode = mHeapDict.Count; mHeapDict[1] = mHeapDict[LastNode]; mHeapDict.Remove(LastNode); MinHeapify(1); return TopNode; } // 根ノードを指定し、根から葉へヒープ構築 private void MinHeapify(long pRootNode) { if (mHeapDict.Count <= 1) { return; } long Left = pRootNode * 2; long Right = pRootNode * 2 + 1; // 左の子、自分、右の子で値が最小のノードを選ぶ long Smallest = mHeapDict[pRootNode].SumCost; long SmallestNode = pRootNode; if (mHeapDict.ContainsKey(Left) && mHeapDict[Left].SumCost < Smallest) { Smallest = mHeapDict[Left].SumCost; SmallestNode = Left; } if (mHeapDict.ContainsKey(Right) && mHeapDict[Right].SumCost < Smallest) { Smallest = mHeapDict[Right].SumCost; SmallestNode = Right; } // 子ノードのほうが大きい場合 if (SmallestNode != pRootNode) { PQueueJyoutaiDef Swap = mHeapDict[SmallestNode]; mHeapDict[SmallestNode] = mHeapDict[pRootNode]; mHeapDict[pRootNode] = Swap; // 再帰的に呼び出し MinHeapify(SmallestNode); } } } #endregion