dijkstra算法模板_HDU3790

问题描述:  有n个点,m个边,每条边上有一个权值,求从s节点到e节点的最短路径,即途径路上的权值和为最小。 

      是求单起点,多终点最短路的问题。

dijkstra算法基本思想

1:设置一个distanse数组,存储从起始点s到各个节点的距离(权值和),distanse[i]即从s到i的最短路

2:初始状态,distanse[i]=mp[s][i],found[s]=1

3:每次从所有 1未访问的节点中  挑出 2distanse最小的点k  choose() 进行松弛操作;

4:松弛操作。如果经过k到j的distanse小于原来的distanse  更新distanse  

    if(dis[k]+mp[k][j]<dis[j])   dis[j]=dis[k]+mp[k][j];

dijkstar 算法的时间复杂度是O(N^2)可以用对优化到O(N*LogN)级别

    用了贪心的思想,只能用于正权边,带负权的会导致贪心的bug

本题是两个权,距离和cost,分优先级的进行dijkstra,比较水。

不过还是要注意数组下标别写错了,错一个就是WA!

dijkstra算法只有两个过程 1:选择下一个要操作的点    2:松弛

对图的存储使用  邻接矩阵  和  链式前向星 (感觉和邻接表是一回事)都是一样的,只要稍微改一下代码

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 1005 , INF = 0x3f3f3f;
 5 int mp[maxn][maxn],dis[maxn],fond[maxn],cost[maxn][maxn],wei[maxn];
 6 int n,m,a,b,d,p,s,t;
 7 
 8 void input()
 9 {
10     while(m--)
11     {
12         scanf("%d%d%d%d",&a,&b,&d,&p);
13         if(mp[a][b]>d)
14         {
15             mp[a][b]=mp[b][a]=d;
16             cost[a][b]=cost[b][a]=p;
17         }
18         else if(mp[a][b]==d)
19         {
20             cost[a][b]=cost[b][a]=min(cost[a][b],p);
21         }
22     }
23     cin>>s>>t;
24 }
25 
26 int choose()
27 {
28     int cnt = -1,minn=INF;
29     for(int i=1;i<=n;i++)
30     {
31         if(!fond[i]&&minn>dis[i])
32         {
33             minn=dis[i];
34             cnt=i;
35         }
36     }
37     return cnt;
38 }
39 
40 void dijkstra()
41 {
42     for(int i=1;i<=n;i++)
43     {
44         fond[i]=0;
45         dis[i]=mp[s][i];
46         wei[i]=cost[s][i];
47     }
48     fond[s]=1;
49     for(int i=1;i<=n;i++)
50     {
51         int k=choose();
52         if(k==-1)return ;
53         fond[k]=1;
54         for(int j=1;j<=n;j++)
55         {
56             if(!fond[j])
57             {
58                 if(dis[k]+mp[k][j]<dis[j]){
59                     dis[j]=dis[k]+mp[k][j];
60                     wei[j]=wei[k]+cost[k][j];
61                 }
62                 else if( dis[j]==dis[k]+mp[k][j])
63                 {
64                     wei[j]=min(wei[j],wei[k]+cost[k][j]);
65                 }
66             }
67         }
68     }
69 }
70 
71 int main()
72 {
73     while(cin>>n>>m,n,m)
74     {
75         memset(mp,INF,sizeof(mp));
76         memset(cost,INF,sizeof(cost));
77         input();
78         dijkstra();
79         cout<<dis[t]<<" "<<wei[t]<<endl;
80     }
81     return 0;
82 }
View Code

 下面的HDU1874是经典模板题

 dis[t]=0一定要加上

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 205, INF = 10000000;
 5 int mp[maxn][maxn],found[maxn],dis[maxn];
 6 int n,m,s,t,a,b,x;
 7 void input()
 8 {
 9     //memset(mp,INF,sizeof(mp));
10     for(int i=0;i<n;i++)
11         for(int j=0;j<n;j++)
12             mp[i][j]=INF;
13     memset(found,0,sizeof(found));
14     while(m--)
15     {
16         scanf("%d%d%d",&a,&b,&x);
17         if(x<mp[a][b]) mp[a][b]=mp[b][a]=x;
18     }
19     cin>>s>>t;
20 }
21 
22 int  choose()
23 {
24     int cnt=-1,minn=INF;
25     for(int i=0;i<n;i++)
26     {
27         if(!found[i]&&dis[i]<minn)
28         {
29             cnt=i;minn=dis[i];
30         }
31     }
32     return cnt;
33 }
34 
35 void dijkstra()
36 {
37     for(int i=0;i<n;i++)
38     {
39         dis[i]=mp[s][i];
40     }
41     found[s]=1;
42     dis[s]=0;
43     for(int i=0;i<n;i++)
44     {
45         int k=choose();
46         if(k==-1)return;
47         found[k]=1;
48         for(int j=0;j<n;j++)
49         {
50             if(!found[j]&&dis[k]+mp[k][j]<dis[j])
51             {
52                     dis[j]=dis[k]+mp[k][j];
53             }
54         }
55     }
56 }
57 
58 
59 int main()
60 {
61     while(cin>>n>>m)
62     {
63         input();
64         dijkstra();
65         if(dis[t]==INF)cout<<"-1"<<endl;
66         else cout<<dis[t]<<endl;
67 
68     }
69     return 0;
70 }
View Code
落霞与孤鹜齐飞,秋水共长天一色
原文地址:https://www.cnblogs.com/star-and-me/p/6663457.html