最短路再放送

2022-05-05 16:36:15 字數 3208 閱讀 5990

#前言

當我做另一道題使用最短路演算法時,我習慣性地去$luogu$博找$dijksttra$的板子,這時候我覺得這種演算法應該記住,於是我又重溫了一遍最短路演算法,發現了很多困惑,尤其是關於$spfa$和$dijkstra$演算法的區別。因為我的$spfa$和$dijkstra$都使用了堆優化。

然後我困惑了很久,終於明白了,準備推樣例理解一下,又心血來潮重溫了一下$dijkstra$演算法為什麼不能處理負權邊,然後構造了乙個帶負權的有向圖,結果呢。

**我的$dijkstra$竟然跑出了正確的答案!**

我驚了,拿朋友的板子發現正確的$dijkstra$演算法是不能跑負權邊的,於是我再去看我的板子,懷疑我的$dijkstra$寫成了$spfa$,要是我發現了能處理負權邊的$dijkstra$演算法,我估計會被保送吧哈哈。於是改掉了我的板子,所幸在$noip$前發現,在此簡單總結一下最短路演算法。

#$floyed$

多源最短路演算法,運用了鬆弛的思想,有很濃重的$dp$氣息(~~因為它就是$dp$~~),通過列舉中間點轉移。

複雜度$o(n^3)$,在解決最短路問題上基本沒有用處,如果解決多源問題完全可以跑$n$遍$dijkstra$,和矩陣乘法結合有一些用,具體我也忘了。

```memset(f,inf,sizeof(f));

for(int i=1;i<=n;++i) f[i][i]=0;

for(int i=1;i<=n;++i)

for(int j=1;j<=n;++j)

for(int k=1;k<=n;++k)

f[i][j]=min(f[i][j],f[i][k]+f[k][j]);

```#$spfa$

$spfa$是個隨機資料下比較快的演算法,它的思想是每次從佇列中找到乙個點,鬆弛它所連的邊,然後出隊,注意這個點是可以再次被更新的,也就是可以再次入隊重新鬆弛,不斷逼近,直到最後求出最優解。所以卡$spfa$的辦法就是讓$spfa$跑到終點,然後再從起點更新,讓它不停地重複跑就可以了,具體方法是構造乙個網格圖,將橫向邊邊權設為很小,縱邊很大即可。

$spfa$最優複雜度為$o(ke)$,其中$k$是乙個常數,但是最壞情況可以達到$o(ve)$

眾所周知,現在很多最短路題目出題人都會卡$spfa$,用雙端佇列優化或者是堆優化本質都是不變的,都會被卡,所以還是用$dijkstra$吧。

**常規的$spfa$**

```#include#define n 10005

#define maxn 500005

#define inf 2147483647

using namespace std;

int dis[n],cnt,n,m,eu,ev,head[n],x,y,z,s;

bool vis[n];

struct edgee[maxn];

inline void add(int u,int v,int w)

void spfa(int s)

dis[s]=0;

queue q;

q.push(s);

vis[s]=false;

while(!q.empty())

while(ch>='0'&&ch<='9')

return x*f;

}int main()

spfa(s);

for(register int i=1;i<=n;i++) printf("%d ",dis[i]);

}```

**比較常用的雙端佇列優化($slf$優化),大概思想是隊列為空或者當前最短距離比隊首小時放到隊首,否則放到隊尾,最好再熟悉一下$stl$**

```#include#define n 100005

#define maxn 200005

#define inf 2147483647

using namespace std;

int dis[n],cnt,n,m,eu,ev,head[n],x,y,z,s;

bool vis[n];

struct edgee[maxn];

inline void add(int u,int v,int w)

void spfa(int s)

dis[s]=0;

deque q;

q.push_back(s);

vis[s]=1;

while(!q.empty())

if(q.empty()||dis[ev]'9')

while(ch>='0'&&ch<='9')

return x*f;

}int main()

spfa(s);

for(register int i=1;i<=n;i++) printf("%d ",dis[i]);

}```

**$spfa$堆優化:算是比較快的,但是不常用,這個可以過掉洛谷的單源最短路(標準版),而且比$dijkstra$要快**

```#include#define n 200000 + 10

#define maxn 200000 + 10

#define inf 2147483647

using namespace std;

int dis[n],cnt,n,m,eu,ev,head[n],x,y,z,s;

bool vis[n];

struct edgee[maxn];

inline void add(int u,int v,int w)

struct cmp

};void spfa(int s)

e[maxn<<2];

inline void add(int u,int v,int w)

struct node);

//vis[s]=1;

while(!q.empty()));}

}}

}}int main()

dijkstra();

for(re int i=1;i<=n;++i)

printf("%d ",dis[i]);

return 0;

}結構體重載就相當於\(cmp\)函式進行排序

bool operator <(const node&rhs) const{

return rhs.d標準格式如上,上句話的意思是:乙個結構體比另乙個結構體小當且僅當這個結構體的\(d\)大於另乙個結構體的\(d\),\(rhs\)相當於別的結構體

又因為堆預設大根堆,從大到小排序,那麼反過來\(d\)就從小到大排序了。

最短路 最短路徑問題

題目描述 平面上有n個點 n 100 每個點的座標均在 10000 10000之間。其中的一些點之間有連線。若有連線,則表示可從乙個點到達另乙個點,即兩點間有通路,通路的距離為兩點直線的距離。現在的任務是找出從一點到另一點之間的最短路徑。input 共有n m 3行,其中 第一行為乙個整數n。第2行...

最短路徑演算法 最短路

在每年的校賽裡,所有進入決賽的同學都會獲得一件很漂亮的t shirt。但是每當我們的工作人員把上百件的衣服從商店運回到賽場的時候,卻是非常累的!所以現在他們想要尋找最短的從商店到賽場的路線,你可以幫助他們嗎?input 輸入包括多組資料。每組資料第一行是兩個整數n m n 100,m 10000 n...

最短路(最短路之積)

首先考慮暴力維護,顯然極端資料就會炸裂,那麼用什麼來維護呢?考慮乙個很 nb的公式log n m log n log m ok,這道題到此結束 我們只要把乘積轉化為對數,最後再還原就可以了,也不用考慮精度問題,本蒟蒻試著用pow,然後它死了。includeusing namespace std co...