using
System;
using
System.Collections.Generic;
class
Vertex
{
public
int
Id {
get
; }
public
List<
int
> AdjList {
get
; } =
new
List<
int
>();
public
List<
double
> AdjWeights {
get
; } =
new
List<
double
>();
public
Vertex(
int
id)
{
Id = id;
}
}
class
Program
{
static
double
ShortestPath(Vertex[] vertices,
int
N,
int
src,
int
destination)
{
double
[] distTo =
new
double
[N + 1];
double
[] edgeTo =
new
double
[N + 1];
for
(
int
i = 1; i <= N; i++)
distTo[i] =
double
.PositiveInfinity;
distTo[src] = 0.0;
edgeTo[src] =
double
.PositiveInfinity;
PriorityQueue<Tuple<
double
, Vertex>> pq =
new
PriorityQueue<Tuple<
double
, Vertex>>(
Comparer<Tuple<
double
, Vertex>>.Create((a, b) => a.Item1.CompareTo(b.Item1)));
pq.Enqueue(Tuple.Create(distTo[src], vertices[src]));
while
(!pq.IsEmpty)
{
var
pair = pq.Dequeue();
double
dist = pair.Item1;
Vertex closest = pair.Item2;
for
(
int
i = 0; i < closest.AdjList.Count; i++)
{
if
(closest.AdjWeights[i] < edgeTo[closest.Id] &&
distTo[closest.Id] + closest.AdjWeights[i] < distTo[closest.AdjList[i]])
{
edgeTo[closest.AdjList[i]] = closest.AdjWeights[i];
distTo[closest.AdjList[i]] = closest.AdjWeights[i] + distTo[closest.Id];
pq.Enqueue(Tuple.Create(distTo[closest.AdjList[i]],
vertices[closest.AdjList[i]]));
}
}
}
double
firstPass = distTo[destination];
for
(
int
i = 1; i <= N; i++)
distTo[i] =
double
.PositiveInfinity;
distTo[src] = 0.0;
edgeTo[src] = 0.0;
pq.Enqueue(Tuple.Create(distTo[src], vertices[src]));
while
(!pq.IsEmpty)
{
var
pair = pq.Dequeue();
double
dist = pair.Item1;
Vertex closest = pair.Item2;
for
(
int
i = 0; i < closest.AdjList.Count; i++)
{
if
(closest.AdjWeights[i] > edgeTo[closest.Id] &&
distTo[closest.Id] + closest.AdjWeights[i] < distTo[closest.AdjList[i]])
{
edgeTo[closest.AdjList[i]] = closest.AdjWeights[i];
distTo[closest.AdjList[i]] = closest.AdjWeights[i] + distTo[closest.Id];
pq.Enqueue(Tuple.Create(distTo[closest.AdjList[i]],
vertices[closest.AdjList[i]]));
}
}
}
double
secondPass = distTo[destination];
if
(firstPass ==
double
.PositiveInfinity && secondPass ==
double
.PositiveInfinity)
return
-1;
return
Math.Min(firstPass, secondPass);
}
static
void
Main(
string
[] args)
{
int
N = 6;
Vertex[] vertices =
new
Vertex[N + 1];
for
(
int
i = 1; i <= N; i++)
vertices[i] =
new
Vertex(i);
vertices[1].AdjList.Add(3);
vertices[1].AdjWeights.Add(1.1);
vertices[1].AdjList.Add(5);
vertices[1].AdjWeights.Add(2.0);
vertices[1].AdjList.Add(6);
vertices[1].AdjWeights.Add(3.3);
vertices[2].AdjList.Add(5);
vertices[2].AdjWeights.Add(2.7);
vertices[3].AdjList.Add(4);
vertices[3].AdjWeights.Add(2.0);
vertices[3].AdjList.Add(5);
vertices[3].AdjWeights.Add(1.1);
vertices[4].AdjList.Add(2);
vertices[4].AdjWeights.Add(2.3);
vertices[5].AdjList.Add(6);
vertices[5].AdjWeights.Add(2.4);
vertices[6].AdjList.Add(2);
vertices[6].AdjWeights.Add(3.0);
int
src = 1;
int
target = 2;
Console.WriteLine(ShortestPath(vertices, N, src, target));
}
}
class
PriorityQueue<T>
{
private
List<T> list =
new
List<T>();
private
readonly
IComparer<T> comparer;
public
PriorityQueue(IComparer<T> comparer)
{
this
.comparer = comparer;
}
public
void
Enqueue(T item)
{
list.Add(item);
int
childIndex = list.Count - 1;
while
(childIndex > 0)
{
int
parentIndex = (childIndex - 1) / 2;
if
(comparer.Compare(list[childIndex], list[parentIndex]) >= 0)
break
;
T tmp = list[childIndex];
list[childIndex] = list[parentIndex];
list[parentIndex] = tmp;
childIndex = parentIndex;
}
}
public
T Dequeue()
{
int
lastIndex = list.Count - 1;
T frontItem = list[0];
list[0] = list[lastIndex];
list.RemoveAt(lastIndex);
lastIndex--;
int
parentIndex = 0;
while
(
true
)
{
int
leftChildIndex = 2 * parentIndex + 1;
int
rightChildIndex = 2 * parentIndex + 2;
if
(leftChildIndex > lastIndex)
break
;
int
childIndex = leftChildIndex;
if
(rightChildIndex <= lastIndex &&
comparer.Compare(list[leftChildIndex], list[rightChildIndex]) > 0)
childIndex = rightChildIndex;
if
(comparer.Compare(list[parentIndex], list[childIndex]) <= 0)
break
;
T tmp = list[parentIndex];
list[parentIndex] = list[childIndex];
list[childIndex] = tmp;
parentIndex = childIndex;
}
return
frontItem;
}
public
bool
IsEmpty
{
get
{
return
list.Count == 0; }
}
}