这两天做了一道Dijkstra的题,苦于测试没有数据,网站只会po出WA,TLE之类的就很难,所以把我用来测试的几组数放到下面(part3)。
原题
题解
相信大家都能百度到,就是【Dijkstra算法+heap辅助找最小】
测试数据
代码
#include<iostream>
using namespace std;
int MinHeapSize;
int GraphSize;
struct MinHeapNode{
int weight = -1;
int key = -1;
};
// Construct Heap
struct MinHeapTree{
public:
int size = 0;
MinHeapNode** mht = new MinHeapNode*[MinHeapSize];
MinHeapTree(){
for(int i = 0; i < MinHeapSize; i++){
mht[i] = NULL;
}
return;
}
~MinHeapTree(){
delete []mht;
}
void insertion(MinHeapNode* newNode);
int pop();
};
void MinHeapTree::insertion(MinHeapNode* newNode){
//MinHeapNode* addMinHeapNode = new MinHeapNode;
int currentPosition = size;
mht[currentPosition] = newNode;
//Insert Node
int parent;
while(true){
// If currentNode is root
if(currentPosition == 0){
mht[0] = newNode;
break;
}
// If currentNode is not root
else{
//Find Parent Node
if(currentPosition%2 == 0) parent = currentPosition/2-1;
else parent = (currentPosition-1)/2;
if(mht[parent]->weight > newNode->weight){
mht[currentPosition] = mht[parent];
mht[parent] = newNode;
currentPosition = parent;
}
else break;
}
}
size++;
return;
}
int MinHeapTree::pop(){
if(size == 0) return -1;
int result = mht[0]->key;
//move last node to first
MinHeapNode* tmpMinHeapNode = mht[size-1];
MinHeapNode* deleteMinHeapNode = mht[0];
delete deleteMinHeapNode;
mht[size-1] = NULL;
size --;
if(size == 0) return result;
int parent,lchild,rchild;
parent = 0;
mht[parent] = tmpMinHeapNode;
while(true){
//find children
lchild = 2 * parent + 1;
rchild = 2 * parent + 2;
//currentNode is leaf, break
if(lchild >= size) break;
else if(mht[lchild] == NULL) break;
else if(mht[lchild]->weight < mht[parent]->weight
&& mht[rchild] == NULL){
mht[parent] = mht[lchild];
mht[lchild] = tmpMinHeapNode;
parent = lchild;
}
else if(mht[lchild]->weight >= mht[parent]->weight
&& mht[rchild] == NULL){
break;
}
else if(mht[lchild]->weight < mht[parent]->weight
&& mht[lchild]->weight < mht[rchild]->weight){
mht[parent] = mht[lchild];
mht[lchild] = tmpMinHeapNode;
parent = lchild;
}
else if(mht[rchild]->weight < mht[parent]->weight){
mht[parent] = mht[rchild];
mht[rchild] = tmpMinHeapNode;
parent = rchild;
}
else break;
}
return result;
}
struct GraphNode{
int idx = 0;
int dis = 0;
GraphNode* next = NULL;
GraphNode* tail = NULL;
};
struct Graph{
int NumNode = 0;
GraphNode** edge = new GraphNode*[GraphSize];
Graph(){
for(int i = 0; i < GraphSize; i++){
edge[i] = NULL;
}
return;
}
~Graph(){
delete []edge;
}
void addPath(int NodeA, int NodeB, int dis){
GraphNode* tmpGraphNode = new GraphNode;
tmpGraphNode->idx = NodeB;
tmpGraphNode->dis = dis;
if(edge[NodeA] == NULL){
edge[NodeA] = tmpGraphNode;
edge[NodeA]->tail = tmpGraphNode;
}
else{
edge[NodeA]->tail->next = tmpGraphNode;
edge[NodeA]->tail = tmpGraphNode;
}
}
};
void Dijkstra(Graph &G, int s){
MinHeapTree MinHeapTreeA;
int NumNode = G.NumNode;
int* dist = new int[NumNode];
bool* visited = new bool[NumNode];
for(int i = 0; i < NumNode; i++){ //initialize dis[]
dist[i] = -1;
visited[i] = 0;
}
dist[s] = 0;
int count = NumNode-1;
int CurrentIdx = s;
int CurrentDis = dist[s];
int connectedIdx;
int connectedDis;
int newDis;
GraphNode* deleteNode = NULL;
GraphNode* connectedNode = NULL;
while(true){
//each node s in S
if(count == 0
||CurrentIdx == -1) break;
CurrentDis = dist[CurrentIdx];
visited[CurrentIdx] = 1;
connectedNode = G.edge[CurrentIdx];
while(true){
//each node related to s
if(connectedNode == NULL) break;
connectedIdx = connectedNode->idx;
connectedDis = connectedNode->dis;
newDis = connectedDis + CurrentDis;
if(dist[connectedIdx] == -1 || dist[connectedIdx] > newDis){
dist[connectedIdx] = newDis;
MinHeapNode* newMinHeapNode = new MinHeapNode;
newMinHeapNode->key = connectedIdx;
newMinHeapNode->weight = dist[connectedIdx];
MinHeapTreeA.insertion(newMinHeapNode);
}
deleteNode = connectedNode;
connectedNode = connectedNode->next;
delete deleteNode;
}
count--;
while(CurrentIdx != -1){
if(visited[CurrentIdx] == 0) break;
CurrentIdx = MinHeapTreeA.pop();
}
}
visited[s] = 0;
int answer;
for(int i = 1; i < NumNode; i++){
answer = dist[i];
printf("%d\n", answer);
}
delete [] visited;
delete [] dist;
return;
}
int main(){
int N, M, s;
scanf("%d%d%d", &N, &M, &s);
MinHeapSize = M;
GraphSize = N+1;
Graph G;
G.NumNode = N+1;
int NodeA, NodeB, dis;
for(int i = 0; i < M; i++){
scanf("%d%d%d", &NodeA, &NodeB, &dis);
if(NodeA != NodeB){
G.addPath(NodeA, NodeB, dis);
}
}
Dijkstra(G, s);
return 0;
}
代码交上去是全AC的,时间复杂度是 O ( T ) = O ( ∣ E ∣ ∗ l g ∣ V ∣ ) O(T) = O(|E|*lg|V|) O(T)=O(∣E∣∗lg∣V∣)如果哪里可以优化快告诉我