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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

spfa(还不懂--)

發(fā)布時間:2023/11/27 生活经验 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spfa(还不懂--) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

粗略講講SPFA算法的原理,SPFA算法是1994年西安交通大學(xué)段凡丁提出

是一種求單源最短路的算法

算法中需要用到的主要變量

int n; ?//表示n個點,從1到n標(biāo)號

int s,t; ?//s為源點,t為終點

int d[N]; ?//d[i]表示源點s到點i的最短路

int p[N]; ?//記錄路徑(或者說記錄前驅(qū))

queue <int> q; ?//一個隊列,用STL實現(xiàn),當(dāng)然可有手打隊列,無所謂

bool vis[N]; ? //vis[i]=1表示點i在隊列中 vis[i]=0表示不在隊列中

?

幾乎所有的最短路算法其步驟都可以分為兩步

1.初始化

2.松弛操作

?

初始化: d數(shù)組全部賦值為INF(無窮大);p數(shù)組全部賦值為s(即源點),或者賦值為-1,表示還沒有知道前驅(qū)

? ? ? ? ? ? ?然后d[s]=0; ?表示源點不用求最短路徑,或者說最短路就是0。將源點入隊;

    (另外記住在整個算法中有頂點入隊了要記得標(biāo)記vis數(shù)組,有頂點出隊了記得消除那個標(biāo)記)

隊列+松弛操作

讀取隊頭頂點u,并將隊頭頂點u出隊(記得消除標(biāo)記);將與點u相連的所有點v進(jìn)行松弛操作,如果能更新估計值(即令d[v]變小),那么就更新,另外,如果點v沒有在隊列中,那么要將點v入隊(記得標(biāo)記),如果已經(jīng)在隊列中了,那么就不用入隊

以此循環(huán),直到隊空為止就完成了單源最短路的求解

?

SPFA可以處理負(fù)權(quán)邊

定理: 只要最短路徑存在,上述SPFA算法必定能求出最小值。

證明:

  每次將點放入隊尾,都是經(jīng)過松弛操作達(dá)到的。換言之,每次的優(yōu)化將會有某個點v的最短路徑估計值d[v]變小。所以算法的執(zhí)行會使d越來越小。由于我們假定圖中不存在負(fù)權(quán)回路,所以每個結(jié)點都有最短路徑值。因此,算法不會無限執(zhí)行下去,隨著d值的逐漸變小,直到到達(dá)最短路徑值時,算法結(jié)束,這時的最短路徑估計值就是對應(yīng)結(jié)點的最短路徑值。(證畢)

期望的時間復(fù)雜度O(ke), 其中k為所有頂點進(jìn)隊的平均次數(shù),可以證明k一般小于等于2。

?

判斷有無負(fù)環(huán):

  如果某個點進(jìn)入隊列的次數(shù)超過N次則存在負(fù)環(huán)(SPFA無法處理帶負(fù)環(huán)的圖)

?

?

?

SPFA的兩種寫法,bfs和dfs,bfs判別負(fù)環(huán)不穩(wěn)定,相當(dāng)于限深度搜索,但是設(shè)置得好的話還是沒問題的,dfs的話判斷負(fù)環(huán)很快

?

int spfa_bfs(int s)
{queue <int> q;memset(d,0x3f,sizeof(d));d[s]=0;memset(c,0,sizeof(c));memset(vis,0,sizeof(vis));q.push(s);  vis[s]=1; c[s]=1;//頂點入隊vis要做標(biāo)記,另外要統(tǒng)計頂點的入隊次數(shù)int OK=1;while(!q.empty()){int x;x=q.front(); q.pop();  vis[x]=0;//隊頭元素出隊,并且消除標(biāo)記for(int k=f[x]; k!=0; k=nnext[k]) //遍歷頂點x的鄰接表
        {int y=v[k];if( d[x]+w[k] < d[y]){d[y]=d[x]+w[k];  //松弛if(!vis[y])  //頂點y不在隊內(nèi)
                {vis[y]=1;    //標(biāo)記c[y]++;      //統(tǒng)計次數(shù)q.push(y);   //入隊if(c[y]>NN)  //超過入隊次數(shù)上限,說明有負(fù)環(huán)return OK=0;}}}}return OK;}

?

int spfa_dfs(int u)
{vis[u]=1;for(int k=f[u]; k!=0; k=e[k].next){int v=e[k].v,w=e[k].w;if( d[u]+w < d[v] ){d[v]=d[u]+w;if(!vis[v]){if(spfa_dfs(v))return 1;}elsereturn 1;}}vis[u]=0;return 0;
}

總結(jié)

以上是生活随笔為你收集整理的spfa(还不懂--)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。