日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

图论 —— 最短路 —— Bellman-Ford 算法与 SPFA

發布時間:2025/3/17 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图论 —— 最短路 —— Bellman-Ford 算法与 SPFA 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【概述】

Bellman-Ford算法適用于計算單源最短路徑,即:只能計算起點只有一個的情況。

其最大特點是可以處理存在負邊權的情況,但無法處理存在負權回路的情況。

其時間復雜度為:O(V*E),其中,V?是頂點數,E 是邊數。

【算法分析】

Bellman Ford 算法與 Dijkstra 算法的思想相同,只不過 Dijkstra 是每次確定一個最短距離點,并用這個點去更新與之相連的其他邊,而 Ford 算法是每次更新所有的邊,從而確定一個點的最短距離

起始時,認為起點是白點(dis[1]=0),每一次都枚舉所有的邊,必然會有一些邊,連接著白點和藍點。因此每次都能用所有的白點去修改所有的藍點,每次循環也必然會有至少一個藍點變成白點。

以下圖為例

令起點為白點,即:dis[1]=0,dis[2、3、4、5]=∞

遍歷所有邊,將與白點相連的藍點變為白點,即:dis[1]=0,dis[2]=2,dis[3]=1,dis[4]=2,dis[5] =∞

繼續向下遍歷,修改藍點為白點,即:dis[1]=0,dis[2]=2,dis[3]=1,dis[4]=2,dis[5] =4

【算法核心】

設起點為 s,dis[v] 表示從 s 到 v 的最短路徑,u[i] 和 v[i] 分別表示第 i 條邊的起點和終點,w[j] 是連接 u、v 的邊 j 的長度。

初始化:

dis[s]=0,dis[v]=0x3f3f3f3f(v≠s),即:初始化為一極大值

算法主體:

void Bellman_Ford() {for(int i=0;i<n;i++) dis[i]=INF;dis[0]=0;for(int i=1;i<=n-1;i++)//枚舉除終點外的所有點for(int j=1;j<=m;j++)//枚舉所有邊{int x=u[j];//邊j的起點int y=v[j];//邊j的終點if(dis[x]<INF)//松弛dis[y]=min(dis[y],dis[x]+w[j]);} }

算法結束:dis[v] 即為 s 到 v 最短距離

【SPFA】

SPFA 實質就是?Ford 算法加了判斷負環的隊列實現版本。

其利用隊列以進行 Ford 算法的過程,初始時將起點加入隊列,每次從隊列中取出一個元素,并對所有與它相鄰的點進行修改,若相鄰的點修改成功,則將其入隊,直到隊列為空時算法結束。

SPFA 時間復雜度可達:O(k*E),其中,E 是邊數,k 是常數,平均值是 2。

int dis[N]; bool vis[N]; void SPFA(int S) {memset(vis, false, sizeof(vis));memset(dis, INF, sizeof(dis));dis[S] = 0;queue<int> Q;Q.push(S);while (!Q.empty()) {int x = Q.front();Q.pop();vis[x] = false;for (int i = head[x]; i != -1; i = edge[i].next) {int to = edge[i].to;if (dis[to] > dis[x] + edge[i].dis) {dis[to] = dis[x] + edge[i].dis;if (!vis[to]) {vis[to] = true;Q.push(to);}}}} }

【SPFA 的 SLF 優化】

在 SPFA 的基礎上,可以進一步的進行優化,即 SLF 優化

SLF 優化就是 small label first 優化,由于先擴展最小的點可以盡量使程序盡早結束,因此當加入一個新點 u 的時候,如果此時的 dis[u] 比隊首的 dis[q.front()] 小的話,就將點 v 加入隊首,否則加入隊尾,利用 STL 中的雙端隊列 deque 即可??

struct Edge{int to,dis; }; vector<Edge> edge[N]; bool vis[N]; int dis[N]; void SPFA(int s) {memset(dis, INF, sizeof(dis));memset(vis, false, sizeof(vis));vis[s] = true;dis[s] = 0;deque<int> Q;Q.push_back(s);while (!Q.empty()) {int x = Q.front();Q.pop_front();vis[x] = 0;for (int i = 0; i < edge[x].size(); i++) {int y = edge[x][i].to;if (dis[y] > dis[x] + edge[x][i].to) {dis[y] = dis[x] + edge[x][i].to;if (!vis[y]) {vis[y] = true;if (!Q.empty() && dis[y] < dis[Q.front()])//加入隊首Q.push_front(y);else//加入隊尾Q.push_back(y);}}}} }

【模版】

1.標準版

struct Edge {int to, next;int dis; } edge[N]; int head[N], tot; bool vis[N]; int dis[N]; void addEdge(int x, int y, int dis) {edge[++tot].to = y;edge[tot].dis = dis;edge[tot].next = head[x];head[x] = tot; } void SPFA(int S) {memset(vis, false, sizeof(vis));memset(dis, INF, sizeof(dis));dis[S] = 0;queue<int> Q;Q.push(S);while (!Q.empty()) {int x = Q.front();Q.pop();vis[x] = false;for (int i = head[x]; i != -1; i = edge[i].next) {int to = edge[i].to;if (dis[to] > dis[x] + edge[i].dis) {dis[to] = dis[x] + edge[i].dis;if (!vis[to]) {vis[to] = true;Q.push(to);}}}} } int main(){int n,m;while(scanf("%d%d",&n,&m)!=EOF){memset(head,-1,sizeof(head));for(int i=1;i<=m;i++){int x,y,dis;scanf("%d%d%d",&x,&y,&dis);//無向圖添邊兩次addEdge(x,y,dis);addEdge(y,x,dis);}int S;scanf("%d",&S);SPFA(S);for(int i=1;i<=n;i++)printf("%d\n",dis[i]);} return 0; }

2.帶負環判斷的SPFA

struct Edge {int from, to;int dis;Edge() {}Edge(int from, int to, int dis) : from(from), to(to), dis(dis) {} }; struct SPFA {int n, m;Edge edges[N]; //所有的邊信息int head[N]; //每個節點鄰接表的頭int next[N]; //每個點的下一條邊int pre[N]; //最短路中的上一條弧bool vis[N];int dis[N];int cnt[N]; //進隊次數void init(int n) {this->n = n;this->m = 0;memset(head, -1, sizeof(head));}void AddEdge(int from, int to, int dist) {edges[m] = Edge(from, to, dist);next[m] = head[from];head[from] = m++;}bool negativeCycle(int s) { //判負環memset(vis, false, sizeof(vis));memset(cnt, 0, sizeof(cnt));memset(dis, INF, sizeof(dis));dis[s] = 0;queue<int> Q;Q.push(s);while (!Q.empty()) {int x = Q.front();Q.pop();vis[x] = false;for (int i = head[x]; i != -1; i = next[i]) {Edge &e = edges[i];if (dis[e.to] > dis[x] + e.dis) {dis[e.to] = dis[x] + e.dis;pre[e.to] = i;if (!vis[e.to]) {vis[e.to] = true;Q.push(e.to);if (++cnt[e.to] > n)return true;}}}}return false;} } spfa; int main() {int n, m;while (scanf("%d%d", &n, &m) != EOF) {spfa.init(n);int S;scanf("%d", &S);for (int i = 1; i <= m; i++) {int x, y, dis;scanf("%d%d%d", &x, &y, &dis);//無向邊添邊兩次spfa.AddEdge(x, y, dis);spfa.AddEdge(y, x, dis);}spfa.negativeCycle(S);for (int i = 1; i <= n; i++)printf("%d\n", spfa.dis[i]);}return 0; }

?

總結

以上是生活随笔為你收集整理的图论 —— 最短路 —— Bellman-Ford 算法与 SPFA的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲视频天堂 | 人人爱超碰 | 日韩色在线观看 | 你懂的国产在线 | 亚洲欧美激情另类 | 久久avav| 二区三区不卡 | 制服丝袜影音先锋 | 粉嫩精品久久99综合一区 | 欧美福利网址 | 国产精品v | 久久超碰精品 | 91视频.com | 婷婷深爱激情 | 日批在线视频 | 91色在线播放 | 四虎在线观看视频 | 亚洲影院中文字幕 | 欧美午夜精品理论片 | 波多野结衣 一区 | 久久久成人精品视频 | 欧美精品在线一区 | 欧美激情在线 | 国产亚洲精品久久久久动 | 激情在线观看视频 | 国产青青操| 亚洲一区二区在线免费 | 国产尤物视频在线 | 亚洲国产精品99久久久久久久久 | 国产永久免费观看 | 日韩二区三区四区 | 五月婷婷丁香在线 | 老熟妇高潮一区二区三区 | 亚洲综合激情网 | 熟妇人妻一区二区三区四区 | 美女黄色小视频 | 成人美女在线观看 | 少妇高潮一区二区三区99刮毛 | 青青草官网 | 亚洲国产一区视频 | 中文无码精品一区二区三区 | 女人叫床高潮娇喘声录音mp3 | 国产片一区二区 | 国产午夜精品久久久久久久久久 | 国产精品一区二区三区免费 | 男人天堂aaa | 国产精品久久无码一三区 | 黑人又大又粗又长 | 精品人妻无码专区视频 | 国产3p精品一区 | 爽爽窝窝午夜精品一区二区 | 国产欧美又粗又猛又爽 | 久在线观看 | youjizz日本人 | 涩久久 | 国产真实乱偷精品视频 | 亚洲免费在线观看av | 亚洲成人激情视频 | 一级黄色视 | 素人一区二区三区 | www.香蕉视频在线观看 | av九九九| 免费成人黄色网 | av片在线免费观看 | 国产精品一区二区三区四 | 成人在线视频免费 | 国产精品视频在线观看 | 欧美乱码视频 | 色视频在线播放 | 亚洲v国产v | 国产91精 | 亚洲综合图片一区 | 足疗店女技师按摩毛片 | 丰满肉嫩西川结衣av | 中文在线不卡 | 大尺度做爰呻吟舌吻情头 | 国产在线播放一区二区三区 | 日韩一区二区三区精品 | 欧美aⅴ在线 | 在线观看黄色av网站 | 肉丝美足丝袜一区二区三区四 | 亚洲精品国产suv一区 | 日本午夜精品理论片a级app发布 | 国产免费午夜 | 天天噜天天干 | 来吧亚洲综合网 | 怡红院av在线 | 日韩a级片| 欧美乱视频 | 99在线精品视频免费观看软件 | 久久亚洲精精品中文字幕早川悠里 | 波多野结衣在线电影 | 岛国二区三区 | 激情文学综合网 | 91入囗| 国精品一区二区三区 | 久久久久久久久久91 | 国产丝袜美腿一区二区三区 | 日日狠狠久久偷偷四色综合免费 |