public static void TestSkewHeapMergeAndRemove() { var heap1 = new SkewHeap(); heap1.Add(1); heap1.Add(23); heap1.Add(4); heap1.Add(28); heap1.Add(24); heap1.Add(44); heap1.Add(63); Assert.AreEqual(heap1.Root.Value, 1); var heap2 = new SkewHeap(); heap2.Add(13); heap2.Add(99); heap2.Add(17); heap2.Add(201); heap2.Add(49); heap2.Add(105); heap2.Add(57); Assert.AreEqual(heap2.Root.Value, 13); var heap = new SkewHeap(); heap.Root = heap.Merge(heap1.Root, heap2.Root); Assert.AreEqual(heap.Root.Value, 1); heap.Remove(); Assert.AreEqual(heap.Root.Value, 4); }
public void Solve() { if (N == 1) { Console.WriteLine(0); return; } for (int i = 0; i < N; i++) { Array.Sort(XY[i]); } Array.Sort(XY, (a, b) => { if (a[0] == b[0]) { return(a[1].CompareTo(b[1])); } return(a[0].CompareTo(b[0])); }); var minST = new SegTreeMin[2]; var maxST = new SegTreeMax[2]; for (int i = 0; i < 2; i++) { minST[i] = new SegTreeMin(N); maxST[i] = new SegTreeMax(N); for (int j = 0; j < N; j++) { minST[i].Update(j, XY[j][i]); maxST[i].Update(j, XY[j][i]); } } var SH = new SkewHeap <Pair>(); for (int i = 1; i < N; i++) { SH.Push(new Pair(i, XY[i][1])); } long ans = (maxST[0].Max - minST[0].Min) * (maxST[1].Max - minST[1].Min); while (SH.Count > 0) { var p = SH.Top; SH.Pop(); int idx = p.Pos; maxST[0].Update(idx, XY[idx][1]); maxST[1].Update(idx, XY[idx][0]); minST[0].Update(idx, XY[idx][1]); minST[1].Update(idx, XY[idx][0]); var v = (maxST[0].Max - minST[0].Min) * (maxST[1].Max - minST[1].Min); ans = Math.Min(ans, v); } Console.WriteLine(ans); }
//ビームの更新 private void UpdateBeam(SkewHeap heap, HashSet <long> puzzlesInHeap, Puzzle nextPuzzle, int beamWidth) { if (heap.Count == beamWidth) { puzzlesInHeap.Remove(heap.MinValue().boardHash); heap.Pop(); } puzzlesInHeap.Add(nextPuzzle.boardHash); heap.Push(nextPuzzle); }
public void Solve() { long[] max = new long[3 * N]; var SH = new SkewHeap <long>(); long tot = 0; for (int i = 0; i < N; i++) { SH.Push(A[i]); tot += A[i]; } max[N - 1] = tot; for (int i = N; i < 2 * N; i++) { tot += A[i]; SH.Push(A[i]); var mm = SH.Top; SH.Pop(); tot -= mm; max[i] = tot; } long[] min = new long[3 * N]; SH = new SkewHeap <long>(); tot = 0; for (int i = 3 * N - 1; i >= 2 * N; i--) { SH.Push(-A[i]); tot += A[i]; } min[2 * N] = tot; for (int i = 2 * N - 1; i >= N; i--) { tot += A[i]; SH.Push(-A[i]); var mm = SH.Top; SH.Pop(); tot -= -mm; min[i] = tot; } long ans = long.MinValue; for (int i = N - 1; i < 2 * N; i++) { ans = Math.Max(ans, max[i] - min[i + 1]); } Console.WriteLine(ans); }
public void Solve() { bool[] visit = new bool[N]; int[] BN = new int[N]; for (int i = 0; i < N; i++) { BN[i] = -1; } SkewHeap <Pair> SH = new SkewHeap <Pair>(); //visit[S] = true; SH.Push(new Pair(S, S)); BN[S] = S; while (SH.Count > 0) { var p = SH.Top; SH.Pop(); if (visit[p.Pos]) { continue; } visit[p.Pos] = true; BN[p.Pos] = p.Cost; //Console.WriteLine("{0} {1}",p.Pos,p.Cost); foreach (var nxt in E[p.Pos]) { if (BN[nxt] < p.Cost) { BN[nxt] = Math.Min(p.Cost, nxt); SH.Push(new Pair(nxt, BN[nxt])); } } } //Console.WriteLine(String.Join(" ",BN)); var sb = new StringBuilder(); for (int i = 0; i < N; i++) { if (BN[i] >= i) { sb.AppendLine((i + 1).ToString()); } } Console.Write(sb.ToString()); }
public void Solve() { int Inf = (int)1e9; int[] min = new int[K]; for (int i = 0; i < K; i++) { min[i] = Inf; } var SH = new SkewHeap <Pair>(); for (int i = 1; i <= 9; i++) { if (min[i % K] > i) { min[i % K] = i; SH.Push(new Pair(i % K, i)); } } bool[] used = new bool[K]; while (SH.Count > 0) { var p = SH.Top; SH.Pop(); int now = p.Pos; int cost = p.Cost; if (used[now]) { continue; } used[now] = true; for (int j = 0; j < 10; j++) { var nxt = (now * 10 + j) % K; if (min[nxt] > cost + j) { min[nxt] = cost + j; SH.Push(new Pair(nxt, min[nxt])); } } } Console.WriteLine(min[0]); }
//ビームを更新するか private bool IsUpdateBeam(SkewHeap heap, HashSet <long> puzzlesInHeap, Puzzle nextPuzzle, int beamWidth) { if (nextPuzzle == null) { return(false); } if (!puzzlesInHeap.Contains(nextPuzzle.boardHash)) { return(true); } if (heap.Count < beamWidth) { return(false); } if (nextPuzzle.boardHash == heap.MinValue().boardHash) { return(true); } return(false); }
public static void TestSkewHeapCreation() { var heap1 = new SkewHeap(); heap1.Add(1); heap1.Add(23); heap1.Add(4); heap1.Add(28); heap1.Add(24); heap1.Add(44); heap1.Add(63); Assert.AreEqual(heap1.Root.Value, 1); Assert.AreEqual(heap1.Root.LeftChild.Value, 4); Assert.AreEqual(heap1.Root.LeftChild.LeftChild.Value, 63); Assert.AreEqual(heap1.Root.LeftChild.RightChild.Value, 24); Assert.AreEqual(heap1.Root.RightChild.Value, 23); Assert.AreEqual(heap1.Root.RightChild.LeftChild.Value, 44); Assert.AreEqual(heap1.Root.RightChild.RightChild.Value, 28); }
//問題を解く public void Solve(Puzzle initialPuzzle) { IsCanceled = false; ViewPuzzles.Clear(); List <SkewHeap> States = new List <SkewHeap>(); int beamWidth = 50; int nowDepth = 0; int maxDepth = initialPuzzle.pieces.Count; for (int i = 0; i < 100; i++) { States.Add(new SkewHeap()); } States[0].Push(initialPuzzle); ViewPuzzles.Add(initialPuzzle); //0手目の結果 //パズルを解く (1手進める) → ビームサーチ while (nowDepth < maxDepth) { HashSet <long> puzzlesInHeap = new HashSet <long>(); States[nowDepth + 1] = new SkewHeap(); while (States[nowDepth].Count > 0) { Puzzle nowPuzzle = States[nowDepth].Pop().Clone(); SetNextStates(nowPuzzle, beamWidth, States[nowDepth + 1], puzzlesInHeap); if (IsCanceled) { return; } } if (States[nowDepth + 1].Count > 0) { ViewPuzzles.Add(States[nowDepth + 1].MaxValue().Clone()); nowDepth++; } else { break; } } }
/// <summary> /// heap同士のマージを行います /// 計算量:O(logN) /// </summary> /// <param name="sh"></param> public void Merge(SkewHeap <T> sh) { root = Merge(root, sh.root); Count += sh.Count; }
//ビームサーチの次状態更新 private void SetNextStates(Puzzle puzzle, int beamWidth, SkewHeap heap, HashSet <long> puzzlesInHeap) { List <Poly> polys = new List <Poly>(puzzle.wakus); for (int i = 0; i < puzzle.pieces.Count; i++) { polys.Add(puzzle.pieces[i]); } for (int dstPolyId = 0; dstPolyId < polys.Count; dstPolyId++) { Poly dstPoly = polys[dstPolyId]; if (!dstPoly.isExist) { continue; } for (int srcPolyId = 0; srcPolyId < puzzle.pieces.Count; srcPolyId++) { Poly srcPoly = puzzle.pieces[srcPolyId]; if (!srcPoly.isExist) { continue; } if (dstPoly == srcPoly) { continue; } for (int dstPointId = 0; dstPointId < dstPoly.Count; dstPointId++) { for (int srcPointId = 0; srcPointId < srcPoly.Count; srcPointId++) { //配置情報でsrcPolyが与えられている場合 if (srcPoly.isPositionDetected) { if (Point.Compare(srcPoly.points[srcPointId], dstPoly.points[dstPointId]) != 0) { continue; } } for (int option = 0; option < 4; option++) { if (IsCanceled) { return; } int direction = option >> 1; // means : option / 2 bool turnflag = (option & 1) == 1; // means : (option % 2) == 1 //配置情報でsrcPolyが与えられている場合 if (srcPoly.isPositionDetected) { if (turnflag) { continue; } Point mul = (dstPoly[dstPointId + direction] - dstPoly[dstPointId]) / (srcPoly[srcPointId - direction] - srcPoly[srcPointId]); if (mul.Re != 1 || mul.Im != 0) { continue; } } int score = getScore(dstPoly, srcPoly, dstPointId, srcPointId, direction, turnflag, heap.Count == beamWidth ? heap.MinValue().boardScore + 1 - puzzle.boardScore : -1); if (score < 0) { continue; } Puzzle nextPuzzle = GetNextPuzzle(puzzle, dstPolyId, srcPolyId, dstPointId, srcPointId, direction, turnflag, score); if (IsUpdateBeam(heap, puzzlesInHeap, nextPuzzle, beamWidth)) { UpdateBeam(heap, puzzlesInHeap, nextPuzzle, beamWidth); } } } } } } }
public void Merge(SkewHeap <T> heap) { root = Meld(root, heap.root); }
public void Solve() { long Inf = (long)1e18; long[] ma = new long[N + 1]; for (int i = 0; i <= N; i++) { ma[i] = -Inf; } Pair[] P = new Pair[N]; for (int i = 0; i < N; i++) { P[i] = new Pair(i, D[i]); } Array.Sort(P, (p, q) => - 1 * (p.D.CompareTo(q.D))); var SH = new SkewHeap <Pair>(); int[] cnt = new int[N]; long tD = 0; var h = new HashSet <int>(); for (int i = 0; i < K; i++) { tD += D[P[i].Idx]; cnt[T[P[i].Idx]]++; h.Add(T[P[i].Idx]); if (cnt[T[P[i].Idx]] > 1) { SH.Push(P[i]); } } ma[h.Count] = tD; for (int i = K; i < N; i++) { int nt = T[P[i].Idx]; if (h.Contains(nt)) { continue; } if (SH.Count == 0) { continue; } h.Add(nt); var p = SH.Top; SH.Pop(); tD -= p.D; tD += P[i].D; ma[h.Count] = Math.Max(tD, ma[h.Count]); } long ans = -Inf; for (int i = 0; i <= N; i++) { if (ma[i] == -Inf) { continue; } ans = Math.Max(ans, (long)i * (long)i + ma[i]); } Console.WriteLine(ans); }
public void Solve() { int NN = N + 2; double[][] dist = new double[NN][]; for (int i = 0; i < NN; i++) { dist[i] = new double[NN]; } for (int i = 0; i < NN; i++) { for (int j = i + 1; j < NN; j++) { if ((X[i] - X[j]) * (X[i] - X[j]) + (Y[i] - Y[j]) * (Y[i] - Y[j]) < (R[i] + R[j]) * (R[i] + R[j])) { dist[i][j] = dist[j][i] = 0; } else { dist[i][j] = dist[j][i] = Math.Sqrt((double)((X[i] - X[j]) * (X[i] - X[j]) + (Y[i] - Y[j]) * (Y[i] - Y[j]))) - (double)(R[i] + R[j]); } } } //for(int i=0;i<NN;i++) Console.WriteLine(String.Join(" ",dist[i])); double[] Min = new double[NN]; for (int i = 1; i < NN; i++) { Min[i] = 1e15; } bool[] used = new bool[NN]; int cntused = 0; var SH = new SkewHeap <Pair>(); SH.Push(new Pair(0, 0)); while (SH.Count > 0) { var p = SH.Top; SH.Pop(); int now = p.Pos; if (used[now]) { continue; } used[now] = true; Min[now] = p.Cost; cntused++; if (cntused == NN) { break; } for (int j = 0; j < NN; j++) { if (Min[j] > Min[now] + dist[now][j]) { Min[j] = Min[now] + dist[now][j]; SH.Push(new Pair(j, Min[j])); } } } Console.WriteLine(Min[NN - 1]); }
/// <summary> /// SubDendriteを距離閾値に従ってMainDendriteに接続 /// </summary> public void ConnectSubDendritesToMainDendrite() { // nodelist[0] : main // nodelist[1:] : sub List <List <DendriteNode> > nodelist = new List <List <DendriteNode> >(); //メインクラスタの分岐,端点ノードを取得 List <DendriteNode> pnode = main_dendrite.GetEdgeNodeAndBranchNodes(); nodelist.Add(pnode); NotMergedSubDendritesIdx = new HashSet <int>(); for (int i = 0; i < sub_dendrites.Count; i++) { //サブクラスタの分岐,端点ノードを取得 List <DendriteNode> node = sub_dendrites[i].GetEdgeNodeAndBranchNodes(); nodelist.Add(node); NotMergedSubDendritesIdx.Add(i); } var Q = new SkewHeap <NodeRelation>(); for (int i = 0; i < nodelist[0].Count; i++) { for (int j = 1; j < nodelist.Count; j++) { double normMin = double.MaxValue; int argMin = -1; for (int k = 0; k < nodelist[j].Count; k++) { double d = nodelist[0][i].EuclideanDistanceTo(nodelist[j][k]); if (d <= normMin) { normMin = d; argMin = k; } } if (argMin != -1 && normMin <= param.distanceThreshold) { Q.Push(new NodeRelation(normMin, i, j, argMin)); } } } while (true) { NodeRelation rel = null; while (Q.Empty() == false) { rel = Q.Pop(); if (nodelist[rel.SlaveClusterIdx].Count > 0) { break; } } if (Q.Empty()) { break; } DendriteNode parent = nodelist[0][rel.MasterNodeIdx]; DendriteNode cand = nodelist[rel.SlaveClusterIdx][rel.SlaveNodeIdx]; //連結ノードにお互いを追加 cand.AddConnectedNode(parent); parent.AddConnectedNode(cand); int mainNodeSizePrev = nodelist[0].Count; //連結したサブノードリストはメインノードリストに吸収 nodelist[0].AddRange(nodelist[rel.SlaveClusterIdx]); //サブを消去 nodelist[rel.SlaveClusterIdx].Clear(); // マージされた NotMergedSubDendritesIdx.Remove(rel.SlaveClusterIdx - 1); // 吸収されたサブノードから、吸収されていないサブノードまでの距離を算出 for (int i = mainNodeSizePrev; i < nodelist[0].Count; i++) { for (int j = 1; j < nodelist.Count; j++) { double normMin = double.MaxValue; int argMin = -1; for (int k = 0; k < nodelist[j].Count; k++) { double d = nodelist[0][i].EuclideanDistanceTo(nodelist[j][k]); if (d <= normMin) { normMin = d; argMin = k; } } if (argMin != -1 && normMin <= param.distanceThreshold) { Q.Push(new NodeRelation(normMin, i, j, argMin)); } } } } main_dendrite.ChangeRootNode(main_dendrite.root); pnode = main_dendrite.GetEdgeNodes(); // どうしてFirstでなくてLastなのかよく分からない main_dendrite.ChangeRootNode(pnode.Last()); }
public void Solve() { List <int>[] E = new List <int> [N]; for (int i = 0; i < N; i++) { E[i] = new List <int>(); } for (int i = 0; i < M; i++) { E[U[i]].Add(i); E[V[i]].Add(i); } long Inf = (long)1e18; long[][] min = new long[2][]; for (int i = 0; i < 2; i++) { min[i] = new long[M]; for (int j = 0; j < N; j++) { min[i][j] = Inf; } } int[] strt = new int[] { S, T }; for (int t = 0; t < 2; t++) { var SH = new SkewHeap <Pair>(); bool[] used = new bool[N]; SH.Push(new Pair(strt[t], 0)); min[t][strt[t]] = 0; while (SH.Count > 0) { var p = SH.Top; SH.Pop(); var now = p.Pos; var cost = p.Cost; if (used[now]) { continue; } used[now] = true; min[t][now] = cost; foreach (var ne in E[now]) { long nc = cost + D[ne]; int nv = U[ne] == now ? V[ne] : U[ne]; if (min[t][nv] > nc) { min[t][nv] = nc; SH.Push(new Pair(nv, nc)); } } } } long[][] comb = new long[2][]; HashSet <int> minedge = new HashSet <int>(); for (int t = 0; t < 2; t++) { int fr = strt[t]; int to = strt[t ^ 1]; List <Pair> L = new List <Pair>(); for (int i = 0; i < N; i++) { L.Add(new Pair(i, min[t][i])); } L.Sort((p, q) => p.Cost.CompareTo(q.Cost)); comb[t] = new long[N]; comb[t][fr] = 1; long dmin = min[t][to]; foreach (var pp in L) { int now = pp.Pos; if (min[t][now] >= dmin) { break; } foreach (var ne in E[now]) { long cost = D[ne]; int ttt = U[ne] == now ? V[ne] : U[ne]; if (min[t ^ 1][ttt] + cost == min[t ^ 1][now]) { minedge.Add(ne); comb[t][ttt] += comb[t][now]; if (comb[t][ttt] >= mod) { comb[t][ttt] -= mod; } } } } } long dmax = min[0][T]; long total = (comb[0][T] * comb[1][S]) % mod; bool[] uused = new bool[N]; long remv = 0; for (int i = 0; i < N; i++) { if (min[0][i] == dmax - min[0][i]) { long c = (comb[0][i] * comb[1][i] % mod) * (comb[1][i] * comb[0][i] % mod) % mod; remv += c; if (remv >= mod) { remv -= mod; } } } //Console.WriteLine(total); //Console.WriteLine(remv); foreach (var e in minedge) { int u = U[e]; int v = V[e]; long di = D[e]; if (min[0][u] < min[0][v]) { if (2 * min[0][u] < dmax && 2 * min[0][v] > dmax) { long c = (comb[0][u] * comb[1][v] % mod) * (comb[1][v] * comb[0][u] % mod) % mod; remv += c; if (remv >= mod) { remv -= mod; } } } else if (min[0][u] > min[0][v]) { if (2 * min[0][v] < dmax && 2 * min[0][u] > dmax) { long c = (comb[0][v] * comb[1][u] % mod) * (comb[1][u] * comb[0][v] % mod) % mod; remv += c; if (remv >= mod) { remv -= mod; } } } } long ans = (total + mod - remv) % mod; Console.WriteLine(ans); }
public void Solve() { List <int>[] E = new List <int> [N]; for (int i = 0; i < N; i++) { E[i] = new List <int>(); } for (int i = 0; i < M; i++) { E[U[i]].Add(i); E[V[i]].Add(i); } long Inf = (long)1e18; long[][] min = new long[2][]; long[][] comb = new long[2][]; for (int i = 0; i < 2; i++) { min[i] = new long[N]; for (int j = 0; j < N; j++) { min[i][j] = Inf; } comb[i] = new long[N]; } int[] strt = new int[] { S, T }; bool[] minedge = new bool[M]; for (int t = 0; t < 2; t++) { var SH = new SkewHeap <Pair>(); bool[] used = new bool[N]; SH.Push(new Pair(strt[t], 0)); min[t][strt[t]] = 0; comb[t][strt[t]] = 1; while (SH.Count > 0) { var p = SH.Top; SH.Pop(); var now = p.Pos; var cost = p.Cost; if (used[now]) { continue; } used[now] = true; min[t][now] = cost; foreach (var ne in E[now]) { long nc = cost + D[ne]; int nv = U[ne] == now ? V[ne] : U[ne]; if (min[t][nv] > nc) { min[t][nv] = nc; SH.Push(new Pair(nv, nc)); } if (used[nv] && min[t][nv] + D[ne] == min[t][now]) { comb[t][now] += comb[t][nv]; // borrow minedge[ne] = true; if (comb[t][now] >= mod) { comb[t][now] -= mod; } } } } } long dmax = min[0][T]; long total = (comb[0][T] * comb[1][S]) % mod; long remv = 0; for (int i = 0; i < N; i++) { if (min[0][i] == dmax - min[0][i]) { long c = (comb[0][i] * comb[1][i] % mod) * (comb[1][i] * comb[0][i] % mod) % mod; remv += c; if (remv >= mod) { remv -= mod; } } } for (int e = 0; e < M; e++) { int u = U[e]; int v = V[e]; long di = D[e]; if (!minedge[e]) { continue; } if (min[0][u] < min[0][v]) { if (min[0][v] > dmax) { continue; } if (min[0][u] + di != min[0][v]) { continue; } if (min[0][u] + min[1][v] + di != dmax) { continue; } if (2 * min[0][u] < dmax && 2 * min[0][v] > dmax) { long c = (comb[0][u] * comb[1][v] % mod) * (comb[1][v] * comb[0][u] % mod) % mod; remv += c; if (remv >= mod) { remv -= mod; } } } else if (min[0][u] > min[0][v]) { if (min[0][u] > dmax) { continue; } if (min[0][v] + di != min[0][u]) { continue; } if (min[0][v] + min[1][u] + di != dmax) { continue; } if (2 * min[0][v] < dmax && 2 * min[0][u] > dmax) { long c = (comb[0][v] * comb[1][u] % mod) * (comb[1][u] * comb[0][v] % mod) % mod; remv += c; if (remv >= mod) { remv -= mod; } } } } long ans = (total + mod - remv) % mod; Console.WriteLine(ans); }
public void Solve() { var ST = new SegTree[2]; for (int i = 0; i < 2; i++) { ST[i] = new SegTree(N); } for (int i = 0; i < N; i++) { ST[i % 2].Update(i, A[i]); } List <int> ans = new List <int>(); int Inf = (int)1e9; var SH = new SkewHeap <Pair>(); var minIdx = QueryMinIdx(0, N, ST); SH.Push(new Pair(0, N, A[minIdx[0]], A[minIdx[1]])); int[] Idx = new int[N + 2]; for (int i = 0; i < N; i++) { Idx[A[i]] = i; } while (SH.Count > 0) { var p = SH.Top; SH.Pop(); int l = p.L; int r = p.R; int a = p.A; int b = p.B; int aidx = Idx[a]; int bidx = Idx[b]; ans.Add(a); ans.Add(b); ST[aidx % 2].Update(aidx, Inf); ST[bidx % 2].Update(bidx, Inf); if (aidx - l > 1) { var midx = QueryMinIdx(l, aidx, ST); SH.Push(new Pair(l, aidx, A[midx[0]], A[midx[1]])); } if (bidx - (aidx + 1) > 1) { var midx = QueryMinIdx(aidx + 1, bidx, ST); SH.Push(new Pair(aidx + 1, bidx, A[midx[0]], A[midx[1]])); } if (r - (bidx + 1) > 1) { var midx = QueryMinIdx(bidx + 1, r, ST); SH.Push(new Pair(bidx + 1, r, A[midx[0]], A[midx[1]])); } } Console.WriteLine(String.Join(" ", ans)); }
public void Solve() { Dictionary <long, List <Pair2> > E = new Dictionary <long, List <Pair2> >(); int Ext = (int)1e7; long mod = (long)1e9 + 7; for (int i = 0; i < M; i++) { var p0 = P[i] * mod + C[i]; var q0 = Q[i] * mod + C[i]; var p1 = P[i] * mod + Ext; var q1 = Q[i] * mod + Ext; if (!E.ContainsKey(p0)) { E.Add(p0, new List <Pair2>()); } if (!E.ContainsKey(q0)) { E.Add(q0, new List <Pair2>()); } if (!E.ContainsKey(p1)) { E.Add(p1, new List <Pair2>()); } if (!E.ContainsKey(q1)) { E.Add(q1, new List <Pair2>()); } E[p0].Add(new Pair2(q0, 0)); E[q0].Add(new Pair2(p0, 0)); E[p0].Add(new Pair2(p1, 1)); // ???????????1 E[q0].Add(new Pair2(q1, 1)); E[p1].Add(new Pair2(p0, 0)); E[q1].Add(new Pair2(q0, 0)); } long Inf = (long)1e9; Dictionary <long, long> Min = new Dictionary <long, long>(); var SH = new SkewHeap <Pair2>(); var pstart = 0 * mod + Ext; Min.Add(pstart, 0); SH.Push(new Pair2(pstart, 0)); HashSet <long> done = new HashSet <long>(); while (SH.Count > 0) { var now = SH.Top; SH.Pop(); var p = now.Pos; var c = now.Cost; if (done.Contains(p)) { continue; } done.Add(p); Min[p] = c; if (!E.ContainsKey(p)) { continue; } foreach (var nxt in E[p]) { var np = nxt.Pos; var nc = nxt.Cost; if (!Min.ContainsKey(np)) { Min.Add(np, Inf); } if (Min[np] <= c + nc) { continue; } Min[np] = c + nc; SH.Push(new Pair2(np, c + nc)); } } var pend = (N - 1) * mod + Ext; Console.WriteLine(Min.ContainsKey(pend) ? Min[pend] : -1); }