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 }
View Code

优化后:

 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 }
View Code

以下题目可以拿来练练手,几乎是基本模板题

P3371 【模板】单源最短路径(弱化版)

P4779 【模板】单源最短路径(标准版)

Silver Cow Party 

 
 

 

posted @ 2019-07-21 21:20  回忆酿的甜  阅读(287)  评论(0编辑  收藏  举报
Live2D