标签:style blog color os io for ar cti
dijkstra算法,最简单的实现需要$O(|V|^2)$。用binary heap实现,可以优化到O((|V|+|E|)lg|V|),如果用fibonacci heap的话,可以优化到O(|E|+|V|lg|V|)。如果图是密集图的话,那这个优化效果也不好,接近$O(|V|^2)$。
For any implementation of vertex set Q the running time is in $O(|E| \cdot dk_Q + |V| \cdot em_Q)$, where $dk_Q$ and $em_Q$ are times needed to perform decrease key and extract minimum operations in set Q, respectively.
The simplest implementation of the Dijkstra‘s algorithm stores vertices of set Q in an ordinary linked list or array, and extract minimum from Q is simply a linear search through all vertices in Q. In this case, the running time is $O(|E| + |V|^2) = O(|V|^2)$.
For sparse graphs, that is, graphs with far fewer than $O(|V|^2)$ edges, Dijkstra‘s algorithm can be implemented more efficiently by storing the graph in the form of adjacency lists and using a self-balancing binary search tree, binary heap, pairing heap, or Fibonacci heap as a priority queue to implement extracting minimum efficiently. With a self-balancing binary search tree or binary heap, the algorithm requires $\Theta((|E| + |V|) \log |V|)$ time (which is dominated by $\Theta( | E | \log | V | )$, assuming the graph is connected). To avoid $O(|V|)$ look-up in decrease-key step on a vanilla binary heap, it is necessary to maintain a supplementary index mapping each vertex to the heap‘s index (and keep it up to date as priority queue Q changes), making it take only $O(\log|V|)$ time instead. The Fibonacci heap improves this to $O(|E| + |V| \log|V|)$.
1 #include <iostream> 2 #include <string> 3 #include <sstream> 4 #include <fstream> 5 #include <vector> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <queue> 9 #include <map> 10 #define MAX 10000 11 using namespace std; 12 13 struct Node { 14 int dist; 15 int index; 16 Node() {} 17 Node(int i, int d) : index(i), dist(d) {} 18 }; 19 20 ostream &operator<<(ostream& os, Node& node) { 21 os << node.index << "(" << node.dist << ") "; 22 return os; 23 } 24 25 class Dijkstra{ 26 public: 27 Dijkstra():n(0), capacity(100) { 28 this->arr = new Node[capacity]; 29 } 30 31 ~Dijkstra() { 32 delete[] arr; 33 } 34 35 void insert(Node v) { 36 if (n >= capacity) { 37 Node* tmp = new Node[capacity << 1]; 38 memcpy(tmp, arr, sizeof(Node) * capacity); 39 capacity <<= 1; 40 } 41 keyMap[v.index] = n; 42 arr[n++] = v; 43 shiftUp(n - 1); 44 } 45 46 void shiftDown(int st, int ed) { 47 Node tmp = arr[st]; 48 while (st < ed) { 49 int next = -1; 50 int left = st * 2 + 1; // left child node 51 if (left < ed) next = left; 52 else break; 53 int right = st * 2 + 2; 54 if (right < ed && arr[right].dist < arr[next].dist) next = right; 55 if (arr[next].dist < arr[st].dist) { 56 keyMap[arr[next].index] = st; 57 arr[st] = arr[next]; 58 st = next; 59 } else break; 60 } 61 keyMap[tmp.index] = st; 62 arr[st] = tmp; 63 } 64 65 void shiftUp(int ed) { 66 Node tmp = arr[ed]; 67 while (ed > 0) { 68 int parent = (ed - 1) / 2; 69 if (arr[ed].dist < arr[parent].dist) { 70 keyMap[arr[parent].index] = ed; 71 arr[ed] = arr[parent]; 72 ed = parent; 73 } else break; 74 } 75 keyMap[tmp.index] = ed; 76 arr[ed] = tmp; 77 } 78 79 void update(int pos, int v) { 80 if (pos >= n) { 81 arr[pos].dist = v; 82 } else if (arr[pos].dist < v) { 83 arr[pos].dist = v; 84 shiftDown(pos, n); 85 } else { 86 arr[pos].dist = v; 87 shiftUp(pos); 88 } 89 } 90 91 bool empty() const { 92 return n <= 0; 93 } 94 95 Node top() { 96 if (empty()) return Node(); 97 return arr[0]; 98 } 99 100 void pop() { 101 if (empty()) return; 102 keyMap[arr[n - 1].index] = 0; 103 keyMap[arr[0].index] = n - 1; 104 swap(arr[0], arr[n - 1]); 105 shiftDown(0, --n); 106 } 107 108 void load(string filename) { 109 ifstream in(filename.c_str()); 110 string line; 111 getline(in, line); 112 int n = atoi(line.c_str()); 113 114 while (adjList.size() < n && getline(in, line)) { 115 vector<int> neigs; 116 stringstream ss(line); 117 int v = 0; 118 while (ss >> v) { 119 neigs.push_back(v - 1); 120 } 121 adjList.push_back(neigs); 122 } 123 124 while (getline(in, line)) { 125 vector<int> ws; 126 stringstream ss(line); 127 int w = 0; 128 while (ss >> w) { 129 ws.push_back(w); 130 } 131 weights.push_back(ws); 132 } 133 134 for (int i = 0; i < adjList.size(); ++i) { 135 for (int j = 0; j < adjList[i].size(); ++j) { 136 cout << adjList[i][j] << "(" << weights[i][j] << ") "; 137 } 138 cout << endl; 139 } 140 } 141 142 // dijstra using binary heap, O((|V|+|E|)lg|V|) 143 int run() { 144 if (adjList.empty()) return 0; 145 insert(Node(0, 0)); 146 for (int i = 1; i < adjList.size(); ++i) { 147 insert(Node(i, MAX)); 148 } 149 150 while (!empty()) { 151 Node nearest = top(); 152 pop(); // O(|V|lg|V|) 153 154 for (int j = 0; j < adjList[nearest.index].size(); ++j) { 155 int d = nearest.dist + weights[nearest.index][j]; 156 int neig = adjList[nearest.index][j]; 157 if (d < arr[keyMap[neig]].dist) update(keyMap[neig], d); // O(|E|lg|V|) 158 } 159 } 160 161 for (int i = 0; i < adjList.size(); ++i) { 162 cout << arr[i] << " "; 163 } 164 cout << endl; 165 return 0; 166 } 167 168 private: 169 Node* arr; 170 int n; 171 int capacity; 172 map<int, int> keyMap; // from graph index to arr index 173 vector<vector<int> > adjList, weights; 174 }; 175 176 int main() 177 { 178 Dijkstra dij; 179 dij.load("input.txt"); 180 dij.run(); 181 return 0; 182 }
input.txt:
6 2 3 6 1 3 4 1 2 4 6 2 3 5 4 6 1 3 5 7 9 14 7 10 15 9 10 11 2 15 11 6 6 9 14 2 9
每一行是顶点个数;
前几行是邻接列表;后几行是对应的边的权重;
标签:style blog color os io for ar cti
原文地址:http://www.cnblogs.com/linyx/p/3920342.html