Dijkstra+Heap模板
普通Dijkstra:
1 void DijkstraPath(int v0,int vis[],int dist[],int path[]) 2 { 3 int onePath[maxn]; 4 int d; 5 int k; 6 for(int i = 0;i < n;i++) 7 { 8 if( vis[i] && i != v0) 9 { 10 cout<<"Path->"; 11 d = 0; 12 onePath[d] = i;//添加路径上的终点 13 k = path[i]; 14 if(k == -1) 15 { 16 cout<<"No paht"<<endl; 17 } 18 else 19 { 20 while(k != v0) 21 { 22 d++; 23 onePath[d] = k; 24 k = path[k]; 25 } 26 d++; 27 onePath[d] = v0;//添加起点 28 cout<<"Start :"<<onePath[d];//起点 29 for(int j = d - 1;j>=0;j--) 30 { 31 cout<<onePath[j]<<" "; 32 } 33 cout<<endl; 34 } 35 } 36 } 37 } 38 39 void Dijkstra(int v0) 40 { 41 int dist[maxn];//距离数组,每个点到v0的直接距离 42 int path[maxn];//路径数组,记录最短路径上的前驱结点 43 int vis[maxn]; 44 int u;//中间结点 45 memset(dist,0,sizeof(dist)); 46 memset(path,0,sizeof(path)); 47 memset(vis,0,sizeof(vis)); 48 int mindist; 49 for(int i = 0;i < n;i++) 50 { 51 dist[i] = Graph[v0][i]; 52 if(Graph[v0][i] < INF) 53 { 54 path[i] = v0;//开始与v0直连的点记录 55 } 56 else 57 { 58 path[i] = -1; 59 } 60 } 61 vis[v0] = 1;//开始时v0加入最短路中 62 path[v0] = 0; 63 for(int i = 0; i < n-1;i++) 64 { 65 mindist = INF; 66 for(int j = 0;j < n;j++) 67 { 68 if( !(vis[i]) && dist[j] < mindist)//找最短路 69 { 70 mindist = dist[j]; 71 u = j; 72 } 73 } 74 vis[u] = 1; 75 for(int i = 0 ; i < n;i++)//路径更新 76 { 77 if( !(vis[i]))////考虑剩下未访问的边 78 { 79 if( Graph[u][i] < INF && dist[i] > dist[u] + Graph[u][i] ) 80 //中间点的总路程比原来能直达的更短 81 { 82 dist[i] = dist[u] + Graph[u][i]; 83 path[i] = u;//更新前驱结点 84 } 85 } 86 } 87 } 88 //DijkstraPath( v0, vis,dist,path);//输入最短路径 89 }
优化后:
1 const int maxn= 10000002; 2 int n; 3 int m; 4 int p; 5 int cnt; 6 int dist[1002]; 7 int head[1002];//init -1 8 //存放以i为起点的第一条边存储的位置//以i为起点最后的那个编号 9 int point[1002]; 10 11 struct Edge//建图 12 { 13 int v;//edge[i]表示第i条边的终点 14 int w;//edge[i]表示第i条边的权值 即 距离 15 int nxt;//edge[i]表示与第i条边同起点的下一条边的存储位置(上一条边) 16 }edge[maxn]; 17 18 void Add(int x,int y,int w)// x -> y == w 19 {//链式向前星 20 edge[++cnt].v = y; 21 edge[cnt].w = w; 22 edge[cnt].nxt = head[x]; 23 head[x] = cnt; 24 } 25 26 struct node 27 { 28 int u; 29 int d; 30 bool operator< (const node& rhs)const 31 { 32 return d >rhs.d; 33 } 34 }; 35 36 void Dijkstra(int s) 37 { 38 for(int i=1;i<=n;i++) 39 dist[i] = (i==s)? 0:2147483647; 40 priority_queue<node> Q; 41 Q.push((node){s,0});//开始结点进队 42 while (!Q.empty()) 43 { 44 node fr = Q.top(); Q.pop(); 45 int u = fr.u;//2,0 46 int d = fr.d; 47 // cout<<"enqueue:u:"<<u<<" d:"<<d<<endl; 48 // cout<<"~~~"; 49 if (d != dist[u]) continue;//dijkstra中每个点只会出队一次 vis 50 for (int i = head[u];i;i=edge[i].nxt) 51 { 52 // cout<<"i =="<<i<<endl; 53 int v = edge[i].v;//第i条边的终点 54 // cout<<"edge["<<i<<"].v :"<<v<<" "; 55 int w = edge[i].w; 56 // cout<<"edge["<<i<<"].w :"<<w<<" "; 57 // cout<<endl<<"~~~~~~~~~~~"<<endl; 58 if (dist[u]+w < dist[v]) 59 { 60 // cout<<"dist["<<v<<"]"<<dist[v]<<" "<<endl; 61 /// cout<<"dist["<<u<<"] + w :"<<dist[u]+w<<endl; 62 // cout<<"~~~~~~~~~"<<endl; 63 dist[v] = dist[u]+w; 64 // cout<<"dist["<<v<<"] = "<<dist[u]+w<<endl; 65 // cout<<v<<"v,dist["<<v<<"] enqueue"<<endl; 66 Q.push((node){v,dist[v]}); 67 } 68 } 69 } 70 } 71 int main() 72 { 73 cin>>n>>m>>p;//p为特殊点 74 memset(point,0,sizeof(point)); 75 memset(head,-1,sizeof(head)); 76 for(int i=1;i<=m;i++) 77 { 78 int x,y,z; 79 scanf("%d%d%d",&x,&y,&z); 80 Add(x,y,z); 81 } 82 //cout<<"~~~~~~~~~~~~~"<<endl; 83 // for(int i = 1;i <= m;i++) 84 // { 85 // cout<<" head["<<i<<"]"<<head[i]<<" ||"; 86 // cout<<"edge["<<i<<"] ="<<edge[i].v<<" next"<<edge[i].nxt<<endl; 87 // } 88 // cout<<"~~~~~~~~~~~~~~~~~~~~~"<<endl; 89 Dijkstra(p);//p 到其他点的最小距离 90 ... 91 .... 92 return 0; 93 }
以下题目可以拿来练练手,几乎是基本模板题
P3371 【模板】单源最短路径(弱化版)
P4779 【模板】单源最短路径(标准版)
----------------------------------------------------------------------------------------------------------------转载请说明出处----------------------------------------------------------------------------------------------------------------------
你要做一个不动声色的大人了。不准情绪化,不准偷偷想念,不准回头看。去过自己另外的生活。你要听话,不是所有的鱼都会生活在同一片海里。
————————村上春树