题意:以城市1为出发点,城市n为目的地,有若干条限制:要首先攻占城市a才能攻占城市b,问攻占城市n所需的最短时间。
从源点到任意一点的最短路受两个条件的限制:一是源点到自己的最短路,而是源点到限制点的最短路,即限制点最短路f[c] = Math.max(f[c], d[a]);最短路d[c] = Math.max(d[c], f[c]);
因此要确定所有限制点的最短路后才能使用该点松弛其它顶点。充分利用Dijkstra的最优子结构的性质,当一个点的所有限制点的最短路都确定时再将此点放入队列中,参与松弛过程。
public class InvadeMars { int maxn = 3010, maxm = 70010; long inf = 1l<<50; class node { int be, ne; long val; node(int b, int e, long v) { be = b; ne = e; val = v; } } class HEAP { int n; long arr[] = new long[maxn]; int hp[] = new int[maxn], idx[] = new int[maxn]; void build(long a[], int n) { this.n = n; for (int i = 1; i <= n; i++) { arr[i] = a[i]; hp[i] = idx[i] = i; } for (int i = n / 2; i > 0; i--) heapify(i); } void heapify(int i) { int l = i * 2, r = i * 2 + 1, k = i; if (l <= n && arr[l] < arr[k]) k = l; if (r <= n && arr[r] < arr[k]) k = r; if (k != i) { swap(i, k); heapify(k); } } void swap(int i, int j) { idx[hp[i]] = j; idx[hp[j]] = i; long temp = hp[i]; hp[i] = hp[j]; hp[j] =(int)temp; temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } void decreasekey(int i, long v) { i = idx[i]; arr[i] = v; while (i > 1 && arr[i] < arr[i / 2]) { swap(i, i / 2); i /= 2; } } int poll() { int ans =hp[1]; idx[hp[n]] = 1; hp[1] = hp[n]; arr[1] = arr[n--]; heapify(1); return ans; } } class Dijkstra {// 节点编号1--n !! int E[] = new int[maxn], len, n; node buf[] = new node[maxm]; HEAP hp = new HEAP(); void add(int a, int b, long v) { buf[len] = new node(b, E[a], v); E[a] = len++; } void init(int n) { len = 0; this.n = n; Arrays.fill(E, -1); } long d[] = new long[maxn], f[] = new long[maxn]; boolean vis[]=new boolean[maxn]; void solve(int s) { Arrays.fill(d, inf); Arrays.fill(f, 0); Arrays.fill(vis,false); hp.build(d, n); d[s] = 0; hp.decreasekey(s, 0); while (hp.n > 0) { int a = hp.poll(); if(vis[a])continue; vis[a]=true; for (int j = EE[a]; j != -1; j = bb[j].ne) { int c = bb[j].be; f[c] = Math.max(f[c], d[a]); if (--dgr[c] == 0&&d[c]!=inf){ d[c] = Math.max(d[c], f[c]); hp.decreasekey(c, d[c]); } } for (int i = E[a]; i != -1; i = buf[i].ne) { int b = buf[i].be; if (d[a] + buf[i].val < d[b]) { d[b]=d[a] + buf[i].val; if (dgr[b] == 0) hp.decreasekey(b, d[b]); } } } } } node bb[] = new node[maxm]; Dijkstra dij = new Dijkstra(); int EE[] = new int[maxn], len, n; int dgr[] = new int[maxn]; StreamTokenizer in = new StreamTokenizer(new BufferedReader( new InputStreamReader(System.in))); int nextInt() throws IOException { in.nextToken(); return (int) in.nval; } void init() { dij.init(n); len = 0; Arrays.fill(EE, -1); Arrays.fill(dgr, 0); } void add(int a, int b) { bb[len] = new node(b, EE[a], 0); EE[a] = len++; } void run() throws IOException { int cas = nextInt(); while (cas-- > 0) { n = nextInt(); init(); int m = nextInt(); while (m-- > 0) dij.add(nextInt(), nextInt(), nextInt()); for (int i = 1; i <= n; i++) { int k = nextInt(); while (k-- > 0) { int b = nextInt(); dgr[i]++; add(b, i); } } dij.solve(1); System.out.println(dij.d[n]); } } public static void main(String[] args) throws IOException { new InvadeMars().run(); } }