using
System;
using
System.Collections.Generic;
using
System.Linq;
public
class
DijkstraShortestPath
{
static
int
INF = 1000000001;
public
static
int
[] Dijkstra(
int
u,
int
b,
int
n, List<List<Pair>> adj)
{
int
[] dis =
new
int
[n + 1];
for
(
int
i = 0; i <= n; i++)
{
dis[i] = INF;
}
PriorityQueue<Pair> pq =
new
PriorityQueue<Pair>();
pq.Enqueue(
new
Pair(0, u));
dis[u] = 0;
while
(pq.Count > 0)
{
Pair node = pq.Dequeue();
int
d = node.First;
int
v = node.Second;
if
(d > dis[v])
{
continue
;
}
foreach
(Pair edge
in
adj[v])
{
int
to = edge.First;
int
weight = edge.Second;
if
(dis[to] > dis[v] + weight)
{
dis[to] = dis[v] + weight;
pq.Enqueue(
new
Pair(dis[to], to));
}
}
}
return
dis;
}
public
static
int
ShortestPath(
int
n,
int
m,
int
a,
int
b,
int
[][] edges)
{
List<List<Pair>> adj =
new
List<List<Pair>>();
List<Triple> curved =
new
List<Triple>();
for
(
int
i = 0; i <= n; i++)
{
adj.Add(
new
List<Pair>());
}
foreach
(
int
[] edge
in
edges)
{
int
u = edge[0];
int
v = edge[1];
int
w = edge[2];
int
cw = edge[3];
adj[u].Add(
new
Pair(v, w));
adj[v].Add(
new
Pair(u, w));
curved.Add(
new
Triple(u, v, cw));
}
int
[] da = Dijkstra(a, b, n, adj);
int
[] db = Dijkstra(b, a, n, adj);
int
ans = da[b];
foreach
(Triple triple
in
curved)
{
int
u = triple.First;
int
v = triple.Second;
int
cw = triple.Third;
ans = Math.Min(ans, da[u] + cw + db[v]);
ans = Math.Min(ans, da[v] + cw + db[u]);
}
if
(ans >= INF)
{
return
-1;
}
return
ans;
}
public
static
void
Main()
{
int
n = 4, m = 4;
int
a = 2, b = 4;
int
[][] edges = {
new
int
[] { 1, 2, 1, 4 },
new
int
[] { 1, 3, 2, 4 },
new
int
[] { 1, 4, 3, 1 },
new
int
[] { 2, 4, 6, 5 }
};
int
ans = ShortestPath(n, m, a, b, edges);
Console.WriteLine(ans);
}
}
public
class
Pair : IComparable<Pair>
{
public
int
First {
get
;
set
; }
public
int
Second {
get
;
set
; }
public
Pair(
int
first,
int
second)
{
First = first;
Second = second;
}
public
int
CompareTo(Pair other)
{
return
First.CompareTo(other.First);
}
}
public
class
Triple
{
public
int
First {
get
;
set
; }
public
int
Second {
get
;
set
; }
public
int
Third {
get
;
set
; }
public
Triple(
int
first,
int
second,
int
third)
{
First = first;
Second = second;
Third = third;
}
}
public
class
PriorityQueue<T>
where
T : IComparable<T>
{
private
List<T> list =
new
List<T>();
public
int
Count => list.Count;
public
void
Enqueue(T value)
{
list.Add(value);
int
child = list.Count - 1;
while
(child > 0)
{
int
parent = (child - 1) / 2;
if
(list[child].CompareTo(list[parent]) >= 0)
{
break
;
}
T tmp = list[child];
list[child] = list[parent];
list[parent] = tmp;
child = parent;
}
}
public
T Dequeue()
{
if
(list.Count == 0)
{
throw
new
InvalidOperationException(
"Queue is empty."
);
}
T frontItem = list[0];
int
lastIndex = list.Count - 1;
T lastItem = list[lastIndex];
list.RemoveAt(lastIndex);
if
(list.Count > 0)
{
list[0] = lastItem;
int
parent = 0;
while
(
true
)
{
int
leftChild = parent * 2 + 1;
if
(leftChild >= list.Count)
{
break
;
}
int
rightChild = leftChild + 1;
int
minChild = (rightChild < list.Count && list[rightChild].CompareTo(list[leftChild]) < 0) ? rightChild : leftChild;
if
(list[parent].CompareTo(list[minChild]) <= 0)
{
break
;
}
T tmp = list[parent];
list[parent] = list[minChild];
list[minChild] = tmp;
parent = minChild;
}
}
return
frontItem;
}
public
T Peek()
{
if
(list.Count == 0)
{
throw
new
InvalidOperationException(
"Queue is empty."
);
}
return
list[0];
}
public
bool
Contains(T value)
{
return
list.Contains(value);
}
}