最短路

//orz...高中的时候苦练最短路,然而那年noip没有考。再次写起来倍感亲切啊。

//先整理一波最短路的知识。

一、存图方式

1.邻接矩阵

顾名思义,就是以矩阵的方式来存图啦。有n个点,那么图就是map[n][n]啦。

2.邻接表

       和邻接矩阵不同。邻接表是用两点之间的关系来存图的。比如有一条路是x-->y,那么就是在下标为x的数组里插入y,表示存在一条路是x-->y。第一次cpp的邻接表学到了一波新操作。

1 //代码来源:hdoj2722
2 //建立邻接表
3 struct point{
4     int v,num;
5     point(int a,int b){num=a;v=b;}
6 };
7 vector<point> S[maxn*maxn];

ps.第一次用cpp的vector有点点激动。真鸡儿好用啊orz

3.边集数组+链式前向星

(留坑,有点忘了)

二、最短路算法

1.单源最短路—dijkstra

求一个图中两个点之间最短距离的最快的一种方法,要求路径的花费不能有负的。
时间复杂度:O(ElogE)

(大佬们的代码姿势学不来,继续我P式代码风格)

 1 //dijk+邻接矩阵
 2 void dijk(int st){
 3     memset(V,0,sizeof(V));
 4     V[st]=1;
 5     for (int i=1;i<=n;i++) F[i]=A[st][i];
 6     F[st]=Inf;
 7     for (int i=1;i<=n;i++){
 8         int k=st;
 9         for (int j=1;j<=n;j++){
10             if (!V[j] && F[j]<F[k]) k=j;
11         }
12         V[k]=1;
13         for (int j=1;j<=n;j++){
14             if (F[j]>F[k]+A[k][j] && !V[j]) F[j]=F[k]+A[k][j]; 
15         }
16     }
17 }

2.单源最短路—spfa

代码量较小,速度又不错,经常与其他算法组合出现,可以用来判断负环。(突然想起来没练判负环的题)

 1 //spfa+邻接矩阵
 2 void spfa(int st){
 3     queue<int> Q;
 4     memset(V,0,sizeof(V));
 5     V[st]=1;F[st]=0;T[st]=0;
 6     Q.push(st);
 7     while (!Q.empty()){
 8         int pos=Q.front();
 9         Q.pop();
10         V[pos]=0;
11         for (int i=1;i<=n;i++){
12             int temp=F[pos]+A[pos][i];
13             if (temp<F[i]){
14                 F[i]=temp;
15                 T[i]=T[pos]+B[pos][i];
16                 if (!V[i]){
17                     Q.push(i);
18                     V[i]=1;
19                 }
20             }
21             else if(temp==F[i] && T[i]>T[pos]+B[pos][i]){
22                 T[i]=T[pos]+B[pos][i];
23                 if (!V[i]){
24                     Q.push(i);
25                     V[i]=1;
26                 }
27             }
28         }
29     }
30 }
 1 //spfa+邻接表
 2 void spfa(){
 3     queue<int> Q;
 4     for (int i=1;i<=(n+1)*(m+1);i++) F[i]=Inf;
 5     memset(V,0,sizeof(V));
 6     F[1]=0;
 7     V[1]=1;
 8     Q.push(1);
 9     while (!Q.empty()){
10         int pos=Q.front();
11         Q.pop();
12         V[pos]=0;
13         for (int i=0;i<S[pos].size();i++){
14             int temp=F[pos]+S[pos][i].v;
15             int yy=S[pos][i].num;
16             if (temp<F[yy]){
17                 F[yy]=temp;
18                 if (!V[yy]){
19                     Q.push(yy);
20                     V[yy]=1;
21                 }
22             }
23         }
24     }
25 }

(留坑,spfa+链式前向星)

3.多元最短路—floyd

经常做预处理用,能处理出来图中任意两个点之间的最短距离,时间复杂度O(n^3) 。

 1 //floyd+邻接矩阵
 2 void floyd(){
 3     for (int k=1;k<=n;k++){
 4         for (int i=1;i<k;i++){
 5             for (int j=k+1;j<=n;j++){
 6                 if (A[i][j]<A[i][k]+A[k][j]){
 7                     A[i][j]=A[i][k]+A[k][j];
 8                     path[i][j]=path[i][k];
 9                 }
10             }
11         }
12     }
13 }

4.bell-man

 

 1 bool bellman_ford(int s){
 2     queue<int> Q;
 3     memset(inq,0,sizeof(0));
 4     memset(cnt,0,sizeof(cnt));
 5     for (int i=0;i<n;i++) d[i]=inf;
 6     d[s]=0;
 7     inq[s]=1;
 8     Q.push(s);
 9     while (!Q.empty()){
10         int u=Q.front();
11         Q.pop();
12         inq[u]=0;
13         for (int i=0;i<G[u].size();i++){
14             Edge &e=edges[G[u][i]];
15             if (d[u]<inf && d[e.to]>d[u]+e.dist){
16                 d[e.to]=d[u]+e.dist;
17                 p[e.to]=G[u][i];
18                 if (!inq[e.to]){
19                     Q.push(e.to);
20                     inq[e.to]=1;
21                     if (++cnt[e.to]>n) return 0;
22                 }
23             }
24         }
25     }
26 }

 

 

原文地址:https://www.cnblogs.com/changer-qyz/p/8437134.html