Dijkstra+堆优化

此前没写过,也没看过最大堆最小堆,因为Treap的应用比堆要广,Treap时间复杂度还是比较可观的,但这次看了下最大堆最小堆,就写下来做笔记了,当然还可以使用STL的priority_queue还现实,我就不八婆了!

最大堆最小堆入门:http://www.java3z.com/cwbwebhome/article/article1/1362.html?id=4745

Dijkstra最短路径算法:http://zh.wikipedia.org/zh-cn/Dijkstra%E7%AE%97%E6%B3%95

                                     http://baike.baidu.com/link?url=G_fEz4sLlD3Ot0LH3jN-k8xBsWstMTKGfbFfpdGrXf0zqkZGoz2B_r0OoYOPSn8hCF0i78c0oVGVM2ibT7sfPK

问题描述

给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。

输入格式

第一行两个整数n, m。

接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。

输出格式
共n-1行,第i行表示1号点到i+1号点的最短路。
样例输入
3 3
1 2 -1
2 3 -1
3 1 2
样例输出
-1
-2
数据规模与约定

对于10%的数据,n = 2,m = 2。

对于30%的数据,n <= 5,m <= 10。

对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。

#include
#include
#include
#include
#include
using namespace std;
#define N 20010
#define inf 0x3fffffff
struct node{
	int to, v,next;
}t[N * 10], d[N];
int a[N],v[N],h[N],n;
class Heap{
	int size;
public:
	Heap() :size(n){}
	bool isEmpty(){ return size <= 0; }
	void exch(int i, int j){
		swap(d[h[i]].next, d[h[j]].next);
		swap(h[i], h[j]);
	}
	void up(int x){
		while (x > 1){
			if (d[h[x]].v < d[h[x / 2]].v){
				this->exch(x, x/2);
				x /= 2;
			}else break;
		}
	}
	void down(int x){
		while (x + x <= size){
			int k = x + x;
			if ((k <= size && (d[h[k]].v < d[h[x]].v))||//left child
                (++k <= size && (d[h[k]].v < d[h[x]].v))){//right child
				this->exch(x, k);
				x = k;
			} else break;
		}
	}
	void push(int x){
		h[++size] = x;
		d[x].next = size;
		this->up(size);
	}
	void pop(int x){
		this->exch(x, size);
		d[h[size--]].next = -1;
		down(x);
	}
};
void dijkstra(){
	memset(v, 0, sizeof(v));
	Heap heap;
	for (int i = 1; i <= n; ++i){
		d[i].v = inf;
		d[i].next = h[i] = i;//next is point to heap position,h[i] is point to d[k]'s k
	}
	d[1].v = 0;
	heap.pop(d[1].next);
	for (int i = a[1]; i != -1; i = t[i].next){
		d[t[i].to].v = t[i].v;
		heap.up(d[t[i].to].next);
	}
	for (int i = 0; i < n&&!heap.isEmpty(); ++i){
		int k = h[1];
		heap.pop(1);//remove min
		v[k] = 1;
		//printf("Min:%d\n", k);
		for (int j = a[k]; j != -1; j = t[j].next){
			int mn= d[k].v + t[j].v;
			if (v[t[j].to] || d[t[j].to].v <= mn)continue;
			d[t[j].to].v = mn;
			heap.up(d[t[j].to].next);
			//printf("1->%d->%d:%d\n", k, t[j].to, mn);
		}
	}
}
int main(){
	int m,x,y,z,cnt;
	while (~scanf("%d%d", &n, &m)){
		cnt = 0;
		memset(a, -1, sizeof(a));
		while (m--){
			scanf("%d%d%d", &x, &y, &z);
			t[cnt].next = a[x];
			t[cnt].to = y;
			t[cnt].v = z;
			a[x] = cnt++;
		}
		dijkstra();
		for (int i = 2; i <= n; ++i){
			printf("%d\n", d[i].v);
		}
	}
	return 0;
}




你可能感兴趣的:(acm)