最近正好在學最短路徑,藉此機會把學到的知識總結下,一來分享給大家閱讀,二來方便以後自己查閱。
先列一下下面會總結到的求最短路徑的演算法:
1.dijkstra演算法;2.bellman-ford演算法;
3.folyd演算法;
4.spfa演算法;
dijkstra演算法:求單源最短路徑(不帶負權重的環)
step1.初始化,dis[v0]=0,dis[i]=無窮大(i≠v0,表示不可達);
step2.從v-u中選擇使dis[i]值最小的頂點i,將i加入到u中;
step3.更新與i直接相鄰頂點的dis值(dis[j]=min)。
step4.重複step2和step3,直到u=v,停止。
#include #include #include #include #include #include using namespace std;
#define maxn 10000
const int inf=0x3f3f3f3f;
int n, m, ori;
int dis[maxn], pre[maxn];
int cost[maxn][maxn];
struct node
node(int vv, int ll):v(vv), len(ll){}
bool operator < (const node& a) const
};void dijkstra()}}
}void print_path(int pos)
printf("%d\n", ori);
}int main()
dijkstra();
for(int i = 1; i <= n; i++)
return 0;
}
bellman-ford演算法:求單源最短路徑(可帶負權重的環)
假設存在g=,源頂點為v0,u=,dis[i]記錄v0到i的最短距離,pre[i]記錄從v0到i路徑上的i前面的乙個頂點。
step1.初始化,dis[v0]=0,dis[i]=無窮大(i≠v0,表示不可達);
step2.進行迴圈,迴圈下標為從0到v-1(v等於圖中點的個數),在迴圈內部,遍歷所有的邊,進行鬆弛操作;
step3.遍歷圖中所有的邊(edge(u,v)),判斷是否存在這樣情況:d(v) > d (u) + w(u,v),存在則返回false,表示圖中存在從源點可達的權為負的迴路。
#include #include #include #include using namespace std;
#define maxn 10000
const int inf = 0x3f3f3f3f;
struct edge
;int n, m, ori;//點數、邊數、起始點
int dis[maxn], pre[maxn];
vectoredge;
bool bellman_ford()
}bool flag = true;
for(int i = 0; i < edge.size(); i++)
}return flag;
}void print_path(int start)//列印路徑
printf("%d\n", ori);
}int main()
if(bellman_ford())
}else
printf("this map has negative circle\n");
return 0;
}
folyd演算法:所有頂點對最短路徑(不帶負權重的環)
假設存在g=,dis[i][j]記錄i到j的最短距離,path[i][j]記錄從i到j路徑上j的前面的乙個頂點。
step1.將所有頂點對之間距離初始化為無窮大(dis[i][j]=無窮大),然後將輸入的i到j的距離儲存在dis[i][j]中;
step2.依次掃瞄每乙個點,並以其為基點再遍歷所有每一對頂點dis[i][j]的值,看看是否可用過該基點讓這對頂點間的距離更小。
#include #include #include #include #include #include using namespace std;
#define maxn 10000
const int inf = 0x3f3f3f3f;
int dis[maxn][maxn], path[maxn][maxn];
int n, m, ori;
void floyd()
}}void prin_path()
printf("%d\n", i);}}
}}int main()
while(m--)
floyd();
prin_path();
return 0;
}
spfa演算法:單源最短路徑(可帶負權重的環)
假設存在g=,dis[i]記錄v0到i的最短距離,pre[i]記錄從v0到i路徑上i的前面的乙個頂點;
step1.將所有頂點對之間距離初始化為無窮大(dis[i][j]=無窮大),pre[i]=i,vis[i]=0,將源點入隊;
step2.讀取隊頭頂點now,並將隊頭頂點now出隊(記得消除標記),將與點now相連的所有點next進行鬆弛操作,更新dis[next],另外,如果點next沒有在佇列中,那麼要將點next入隊(記得標記),如果已經在佇列中了,那麼就不用入隊(如果某個頂點入隊超過v次,則說明圖中有負環,直接跳出);
step3.重複step2,直到隊空為止就完成了單源最短路的求解。
#include #include #include #include #include using namespace std;
#define maxn 10000
const int inf = 0x3f3f3f3f;
struct edge
edge(int vv, int ww):v(vv), w(ww){}
};int dis[maxn], vis[maxn], pre[maxn];
int cnt[maxn];
int n, m, ori;
vectoredge[maxn];
int spfa()
dis[ori] = 0;
q.push(ori);
vis[ori]=1;
cnt[ori]++;
while(!q.empty())}}
}return 1;
}void print_path(int pos)
printf("%d\n", ori);
}int main()
if(spfa())
else
printf("this map has negative circle\n");
return 0;
}
dijkstra演算法參考:
bellman-ford演算法參考:
folyd演算法參考:
spfa演算法參考:
最短路 求最長最短路,求最短路的路徑
hdu 1595 find the longest of the shortest include include include include include include include include include include include include include defi...
Dijkstra演算法求最短路徑
參考文獻 dijkstra一般的表述通常有兩種方式,一種用永久和臨時標號方式,一種是用open,close表方式,drew為了和下面要介紹的 a 演算法和 d 演算法表述一致,這裡均採用open,close表的方式。大概過程 建立兩個表,open,close。open表儲存所有已生成而未考察的節點,...
Dijkstra演算法求最短路徑
dijkstra演算法用來求最短距離 已經實現了 那麼最短路徑 如何求解並列印出來呢?此處的方法是記錄路徑中結點的前驅 if v未被訪問 以u為中介點可以使起點s到頂點v的最短距離d v 更優 程式具體實現,鄰接矩陣版 n為頂點數,maxv為最大頂點數 int n,g maxv maxv 起點到達各...