此前没写过,也没看过最大堆最小堆,因为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
问题描述
给定一个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 -1
2 3 -1
3 1 2
样例输出
-1
-2
-2
数据规模与约定
对于10%的数据,n = 2,m = 2。
对于30%的数据,n <= 5,m <= 10。
对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
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;
}