图论dijkstra Bellman_Ford与Floyd算法的性质比较与实现
dijkstra,Bellman_Ford,Floyd算法的比较:
:Dijkstra算法,图所有边权值都为非负的;
:Bellman_Ford算法,图中所有边权值可以存在负值,但是不能存在原点可达的负权回路,如果存在负权回路,该算法可以给出判断;
:Floyd算法,不允许所有权值为负的回路,可以求出任意两点间的最短距离,而Dijkstra和Bellman_Ford算法只可以求出任意点到达源点的最短距离;
:Dijkstra算法的思想是贪心,Bellman_Ford和Floyd算法的思想是动态规划
:三者:图中都可以出现正权回路
Bellman_Ford算法实现
时间复杂度O(nm)
1 #define INF 10000
2 queue<int>q;
3 bool inq[1000];//判断是否已经在队列中
4 for(int i=0;i<n;i++)
5 d[i]=INF;
6 d[0]=0;
7 memset(inq,false,sizeof(inq));
8 q.push(0);
9 inq[0]=true;
10 while(!q.empty())
11 {
12 int x=q.front();q.pop();
13 inq[x]=false;
14 for(int i=first[x];i!=NULL;i=next[i])//寻找所有与x相连的点
15 {
16 if(d[v[i]]>d[x]+w[i])//进行松弛操作
17 d[v[i]]=d[x]+w[i];
18 if(!inq[v[i]])
19 {
20 inq[v[i]]=true;
21 q.push(v[i]);
22 }
23 }
24 }
2 queue<int>q;
3 bool inq[1000];//判断是否已经在队列中
4 for(int i=0;i<n;i++)
5 d[i]=INF;
6 d[0]=0;
7 memset(inq,false,sizeof(inq));
8 q.push(0);
9 inq[0]=true;
10 while(!q.empty())
11 {
12 int x=q.front();q.pop();
13 inq[x]=false;
14 for(int i=first[x];i!=NULL;i=next[i])//寻找所有与x相连的点
15 {
16 if(d[v[i]]>d[x]+w[i])//进行松弛操作
17 d[v[i]]=d[x]+w[i];
18 if(!inq[v[i]])
19 {
20 inq[v[i]]=true;
21 q.push(v[i]);
22 }
23 }
24 }
Floyed算法
时间复杂度O(n^3);
动态方程:
当k=0时:d[i][j]=w[i][j]
当k>=1时:d[i][j]=min(d[i][j],d[i][k]+d[k][j])
1 for(int k=0;k<n;k++)
2 for(int i=0;i<n;i++)
3 for(int j=0;j<n;j++)
4 if(d[i][k]+d[k][j]<d[i][j])
5 d[i][j]=d[i][k]+d[k][j]
2 for(int i=0;i<n;i++)
3 for(int j=0;j<n;j++)
4 if(d[i][k]+d[k][j]<d[i][j])
5 d[i][j]=d[i][k]+d[k][j]
Dijkstra算法伪代码及代码
从单个原点出发到所有节点的最短路径。该算法适用于有向图和无向图
初始化G,s
S=空
Q=V[G];
d=无穷
while(!Q.isempty())
{
在d中选出最小值对应的下标为u
S=S+u
Q=Q-u
对于所有从u出发的边(u,y)更新d[y]=min{d[y],d[u]+map[u,y]};
}
利用father数组记录路径
时间复杂度O(n*n)
优化dijkstra算法为:dijkstra+优先队列 时间复杂度O(MlogN);
1 #include<iostream>
2 #include<queue>
3 usingnamespace std;
4 int G[12][12],E[12][12],d[12],mark[12],N,x,y,z;
5 /*
6 x为起点y为终点 z为距离
7 G存储图,E存储边,d存储距离,mark判断该点是否已经算过
8 */
9 struct node
10 {
11 int valu;
12 int index;
13 friend booloperator<(node a,node b)
14 {
15 return a.valu>b.valu;
16 }
17 }t,st;//重载运算符<
18 int main()
19 {
20 while(cin>>N)
21 {
22 for(int i=0;i<12;i++)
23 G[i][0]=0,d[i]=1000,mark[i]=0;//初始化
24 d[1]=0;
25 while(N--)
26 {
27 cin>>x>>y>>z;
28 G[x][++G[x][0]]=y;
29 E[x][++E[x][0]]=z;
30 }
31 priority_queue<node>q;//声明优先队列
32 t.valu=0,t.index=1;
33 q.push(t);
34 while(!q.empty())
35 {
36 t=q.top();
37 q.pop();
38 if(mark[t.index])//如果已经算过则跳过
39 continue;
40 mark[t.index]=1;
41 for(int i=1;i<=G[t.index][0];i++)
42 {
43 if(d[t.index]+E[t.index][i]<d[G[t.index][i]])//松弛操作
44 {
45 d[G[t.index][i]]=d[t.index]+E[t.index][i];
46 st.valu=d[G[t.index][i]];
47 st.index=G[t.index][i];
48 q.push(st);
49 }
50 }
51 }
52 cout<<"原点为1每一点到原点的最短距离为:"<<endl;
53 for(int i=1;i<6;i++)
54 cout<<d[i]<<"";
55 cout<<endl;
56 }
57 }
58 /*
59 9
60 1 2 10
61 1 3 3
62 2 3 1
63 3 2 4
64 2 4 2
65 3 4 8
66 3 5 2
67 4 5 7
68 5 4 9
69 */
2 #include<queue>
3 usingnamespace std;
4 int G[12][12],E[12][12],d[12],mark[12],N,x,y,z;
5 /*
6 x为起点y为终点 z为距离
7 G存储图,E存储边,d存储距离,mark判断该点是否已经算过
8 */
9 struct node
10 {
11 int valu;
12 int index;
13 friend booloperator<(node a,node b)
14 {
15 return a.valu>b.valu;
16 }
17 }t,st;//重载运算符<
18 int main()
19 {
20 while(cin>>N)
21 {
22 for(int i=0;i<12;i++)
23 G[i][0]=0,d[i]=1000,mark[i]=0;//初始化
24 d[1]=0;
25 while(N--)
26 {
27 cin>>x>>y>>z;
28 G[x][++G[x][0]]=y;
29 E[x][++E[x][0]]=z;
30 }
31 priority_queue<node>q;//声明优先队列
32 t.valu=0,t.index=1;
33 q.push(t);
34 while(!q.empty())
35 {
36 t=q.top();
37 q.pop();
38 if(mark[t.index])//如果已经算过则跳过
39 continue;
40 mark[t.index]=1;
41 for(int i=1;i<=G[t.index][0];i++)
42 {
43 if(d[t.index]+E[t.index][i]<d[G[t.index][i]])//松弛操作
44 {
45 d[G[t.index][i]]=d[t.index]+E[t.index][i];
46 st.valu=d[G[t.index][i]];
47 st.index=G[t.index][i];
48 q.push(st);
49 }
50 }
51 }
52 cout<<"原点为1每一点到原点的最短距离为:"<<endl;
53 for(int i=1;i<6;i++)
54 cout<<d[i]<<"";
55 cout<<endl;
56 }
57 }
58 /*
59 9
60 1 2 10
61 1 3 3
62 2 3 1
63 3 2 4
64 2 4 2
65 3 4 8
66 3 5 2
67 4 5 7
68 5 4 9
69 */