分析:因为有单个源点和终点,每条有向道路上都有对应的开销,可以联想到单源最短路算法。而与常见的单源最短路算法的区别则是在松弛操作中对距离的处理上,有两种情况:
1. 当我们到某条道路e上,当前时间和通过e的时间允许我们直接通过e
2. 当我们到某条道路e上,当前时间和通过e的时间不允许我们直接通过e,则我们需要等待curTime % (e.a + e.b)
同时需要注意的是,有可能通过e的时间大于e开放的时间,在这种情况下,我们不可能通过e。则直接忽略这样的道路。
代码:
import java.util.*;
public class FunnyCarRacingUva12661 {
static int count = 1;
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int m = sc.nextInt();
int s = sc.nextInt();
int t = sc.nextInt();
Dijkstra d = new Dijkstra(n);
for (int i = 0; i < m; i++) {
int u = sc.nextInt();
int v = sc.nextInt();
int a = sc.nextInt();
int b = sc.nextInt();
int dist = sc.nextInt();
if (dist <= a) d.addEdge(u, v, dist, a, b);
}
d.dijkstra(s);
System.out.println("Case " + (count++) + ": " + d.d[t]);
}
sc.close();
}
}
class Dijkstra {
final int MAXN = 300 + 5;
int n, m; //n: number of vertices
ArrayList<Edge> edges; //the vector that keeps all edges
IntList[] G; //use integer to keep track of the edge of a vertex in edges
boolean[] done; //to mark whether we have visited a vertex or not
int[] d; //the distance from s to other vertices
int[] p; //an edge on the shortest path
public Dijkstra(int n) {
this.n = n;
d = new int[MAXN];
p = new int[MAXN];
done = new boolean[MAXN];
G = new IntList[MAXN];
for (int i = 0; i <= n; i++) {
G[i] = new IntList();
}
edges = new ArrayList<Edge>();
}
public void addEdge(int from, int to, int dist, int a, int b) {
edges.add(new Edge(from, to, dist, a, b));
m = edges.size();
G[from].add(m - 1); //record the index of edge of u in the edge list
}
public void dijkstra(int s) {
PriorityQueue<HeapNode> Q = new PriorityQueue<HeapNode>();
for (int i = 0; i <= n; i++) {
d[i] = Integer.MAX_VALUE; //initialize the distance
}
d[s] = 0;
Q.add(new HeapNode(0, s));
while (!Q.isEmpty()) {
HeapNode x = Q.poll();
int u = x.u;
int dis = x.d;
if (done[u]) continue;
done[u] = true;
for (int i = 0; i < G[u].size(); i++) {
//modify relaxation process
Edge e = edges.get(G[u].get(i));
int cycle = e.a + e.b;
int time = dis % cycle; //current position at the interval (0, a + b)
int wait = 0;
//if either the road is already closed
//or we cannot pass the road with the time to pass the road
if (time > e.a || time + e.dist > e.a) wait = cycle - time; //update the waiting value
//total cost to pass road e
int cost = e.dist + wait;
if (dis + cost < d[e.to]) {
d[e.to] = dis + cost;
Q.add(new HeapNode(dis + cost, e.to));
}
}
}
}
}
class Edge {
int from, to, dist, a, b;
public Edge(int u, int v, int d, int a, int b) {
from = u;
to = v;
dist = d;
this.a = a; //open for a seconds
this.b = b; //close for b seconds
}
}
class IntList extends ArrayList<Integer> {
}
class HeapNode implements Comparable<HeapNode> {
int d, u; //d is the distance from the source, u is the number of the vertex
public HeapNode(int d, int u) {
this.d = d;
this.u = u;
}
public int compareTo(HeapNode o) {
if (d < o.d) return -1;
return 1;
}
}