现在的位置: 首页 > 综合 > 正文

hdu 3873 Invade the Mars(自写堆优化Dijkstra)

2012年08月22日 ⁄ 综合 ⁄ 共 2466字 ⁄ 字号 评论关闭

题意:以城市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();
	}
}

抱歉!评论已关闭.