//(只贴代码,不做讲解,欢迎纠正)
//用斐波那契堆实现优先队列 //复杂度O(VlogV+E) #include <iostream> #include <algorithm> #include <string.h> #include <string> #define INF 0x3F3F3F3F #define MAXSIZE 1001 using namespace std; int dis[MAXSIZE]; int path[MAXSIZE]; void dijkstra(int v, int start); void pathout(int from, int to); void graphin(int v, int e); struct node { int front, weight; node* next; }graph[MAXSIZE]; template<typename datatype> struct fib_node { fib_node() { degree = 0; parent = NULL; left = NULL; right = NULL; child = NULL; mark = false; } int degree; datatype key; fib_node<datatype> *parent, *left, *right, *child; bool mark; }; //最小堆 template<typename datatype> class fib_heap { public: fib_heap() { ssize = 0; root = NULL; } void push(fib_node <datatype>*x) { x->mark = false; if (ssize) { x->left = root; x->right = root->right; x->right->left = x; root->right = x; if (x->key<root->key) { root = x; } } else { root = x; x->right = x; x->left = x; } ssize++; } void push(datatype k) { fib_node <datatype>*x = new(fib_node<datatype>); x->key = k; this->push(x); } datatype top() { if (ssize) { return root->key; } throw string("in top(), the heap is empty"); } void unio(fib_heap<datatype> *h) { if (h->ssize == 0) return; if (this->ssize == 0) { root = h->root; this->ssize = h->ssize; return; } fib_node <datatype>*tmp = this->root->right; this->root->right = h->root->right; tmp->left = h->root; h->root->right = tmp; this->root->right->left = this->root; this->ssize += h->ssize; h->root = NULL; h->ssize = 0; } int size() { return ssize; } void pop() { if (!ssize) { throw string("in pop(), the heap is empty"); } fib_node<datatype> *now = root->child; while (now) { fib_node <datatype> *nex = now->right; now->right = root->right; now->left = root; root->right = now; now->right->left = now; now->parent = NULL; if (nex->parent == NULL) break; now = nex; } if (ssize == 1) { delete(root); root = NULL; } else { fib_node <datatype> *tmp = root; root->left->right = root->right; root->right->left = root->left; root = root->right; delete(tmp); conslidate(); } ssize--; } void decrease(fib_node<datatype> *x, datatype k) { if (x->key<k) throw(string("in decrease: the key of x is smaller than the new key!")); x->key = k; fib_node <datatype> *y = x->parent; if (y != NULL&&x->key<y->key) { cut(x, y); cascading(y); } if (x->key<root->key) { root = x; } } private: int ssize; void conslidate() { int D = -1; int tmp = ssize; while (tmp) { tmp >>= 1; D++; } ////////////////////////////////// fib_node <datatype>**deg = new(fib_node<datatype>*[D + 1]); memset(deg, 0, sizeof(deg)*(D + 1)); fib_node <datatype> *theend = root->left; fib_node <datatype> *now = root; while (true) { int d = now->degree; fib_node <datatype> *x = now; fib_node <datatype> *nex = now->right; while (deg[d]) { fib_node <datatype> *y = deg[d]; if (y->key<x->key) { swap(x, y); } //将y节点接到x节点的下面 y->right->left = y->left; y->left->right = y->right; y->parent = x; y->mark = false; if (x->child == NULL) { x->child = y; y->right = y; y->left = y; } else { y->right = x->child->right; y->left = x->child; x->child->right = y; y->right->left = y; } x->degree++; deg[d++] = NULL; } deg[d] = x; if (now == theend) break; now = nex; } root = NULL; for (int i = 0; i <= D; i++) { if (deg[i]) { if (root == NULL) { root = deg[i]; root->right = root; root->left = root; } else { deg[i]->left = root; deg[i]->right = root->right; root->right = deg[i]; deg[i]->right->left = deg[i]; if (deg[i]->key<root->key) { root = deg[i]; } } } } } void cut(fib_node<datatype> *x, fib_node<datatype> *y) { if (x->right == x) { y->child = NULL; } else { x->right->left = x->left; x->left->right = x->right; //防止y->child恰好为x y->child = x->right; } y->degree--; x->mark = false; x->right = root->right; x->left = root; root->right = x; x->right->left = x; x->parent = NULL; } void cascading(fib_node<datatype> *x) { fib_node <datatype> *y = x->parent; if (y) { if (!x->mark) { x->mark = true; } else { cut(x, y); cascading(y); } } } fib_node <datatype> *root; }; int main() { int start, v, e; cout << "请输入图(节点编号从0开始):" << endl; cin >> v >> e; graphin(v, e); cout << "请输入起点:" << endl; cin >> start; dijkstra(v, start); for (int i = 0; i<v; i++) { if (i == start) continue; if (dis[i] == INF) continue; cout << "distance(" << start << "," << i << ") = " << dis[i] << " the path is: "; pathout(start, i); cout << endl; } return 0; } void graphin(int v, int e) { memset(graph, 0, sizeof(graph)); for (int i = 0; i<e; i++) { int from, to, w; cin >> from >> to >> w; node *tmp = graph[from].next; //用nex代替graph[from].next,节约时间 node *nex = new(node); graph[from].next = nex; nex->front = to; nex->weight = w; nex->next = tmp; } } struct point { point(int w_=0, int u_=0) { w = w_; u = u_; } int w, u; }; bool operator<(point a, point b) { return a.w < b.w; } //储存每个节点在堆中的位置,用于快速实现decrease-key操作 fib_node <point> *pinheap[MAXSIZE]; void dijkstra(int v, int start) { //bool vis[v]; bool *vis = new(bool[v]); fib_heap <point> unvis; int sizeunvis = v; memset(dis, 0x3F, sizeof(dis)); memset(path, 0xFF, sizeof(path)); memset(vis, 0x00, sizeof(vis)*v); dis[start] = 0; for (int i = 0; i<v; i++) { pinheap[i] = new(fib_node<point>); pinheap[i]->key = point(dis[i],i); unvis.push(pinheap[i]); } while (unvis.size()>0) { point heaptop = unvis.top(); unvis.pop(); int pmin = heaptop.u; vis[pmin] = true; for (node *p = graph[pmin].next; p != NULL; p = p->next) { int f = p->front; int sum = dis[pmin] + p->weight; if (dis[f]>sum) { dis[f] = sum; path[f] = pmin; if (!vis[f]) { unvis.decrease(pinheap[f], point(dis[f],f)); } } } } } void pathout(int from, int to) { if (from == to) { cout << from; return; } pathout(from, path[to]); cout << "->" << to; }
没有评论:
发表评论