最短路(SPFA 反向建邊)

2021-10-02 06:51:17 字數 4291 閱讀 3875

題目描述

給定乙個 nnn 點 mmm 邊的有向帶權圖表示一座城市,起點為 111 。送餐小哥需要給 nnn 個客戶送外賣,第 iii 個客戶的家在第 iii 號點。由於他的車子容量很小,所以一次只能容納乙份外賣,所以送達外賣之後就要回到起點取新的外賣送下一單,直到全部送到位置。

有向圖保證聯通。外賣小哥一定走的最短路。

求送餐小哥走的總路程。

輸入格式

第一行乙個整數 t,表示資料組數。

對於每組資料,第一行兩個整數 n 和 m 。

接下來 m 行,每行三個整數 ui,vi,ci​ 表示每條有向邊。

輸出格式

對於每組資料,輸出一行乙個整數表示答案。

資料範圍

對於 20%20%20% 的資料: 0i≤109,1≤ui,vi≤n

保證答案在long long範圍內。

樣例輸入

22 2

1 2 13

2 1 33

4 61 2 10

2 1 60

1 3 20

3 4 10

2 4 5

4 1 50

樣例輸出

46210

哭了, inf

infin

f 寫成 int

intin

t 型,dij

kdijk

dijk

超時只過了 8

88 組,spf

aspfa

spfa

穩過,剛開始跑一遍 spf

aspfa

spfa

可以得到 1

11 到任意點的最短距離,如果想到得到任意點到 1

11 的最短距離,反向建圖再跑一遍 spf

aspfa

spfa

即可。

#include

using namespace std;

typedef

long

long ll;

const ll inf=

0x3f3f3f3f3f3f3f3f

;const

int maxn=

2e4+10;

const

int maxm=

6e4+10;

int head[maxn]

,cnt,from[maxm]

,to[maxm]

;int n,m;

bool vis[maxn]

;ll dis[maxn]

,cost[maxm]

;struct edgeedge[maxm]

;void

addedge

(int u,

int v,ll w)

void

spfa

(int s)

queue<

int>q; q.

push

(s); dis[s]=0

; vis[s]

=true;

while

(!q.

empty()

)}}}

}int

main()

spfa(1

); ll ans=0;

for(

int i=

1;i<=n;i++

) ans+

=dis[i]

; cnt=0;

for(

int i=

1;i<=n;i++

) head[i]=-

1;for(

int i=

1;i<=m;i++

)addedge

(to[i]

,from[i]

,cost[i]);

spfa(1

);for(

int i=

1;i<=n;i++

) ans+

=dis[i]

;printf

("%lld\n"

,ans);}

return0;

}

dij

kdijk

dijk

鏈式前向星建圖,過 8

88 組。

//tle

#include

using namespace std;

typedef

long

long ll;

typedef pairint>p;

const ll inf=

0x3f3f3f3f3f3f3f3f

;const

int maxn=

2e4+10;

const

int maxm=

6e4+10;

ll dis[maxn]

;int n,m;

int u[maxm]

,v[maxm]

; ll w[maxm]

;struct edge

edge

(int to,ll cost):to

(to)

,cost

(cost)

;}edge[maxm]

; vectorg[maxn]

;void

dijk()

}}}int

main()

dijk()

; ll ans=0;

for(

int i=

1;i<=n;i++

)for

(int i=

1;i<=m;i++

) g[v[i]].

push_back

(edge

(u[i]

,w[i]))

;dijk()

;for

(int i=

1;i<=n;i++

)printf

("%lld\n"

,ans);}

return0;

}

dij

kdijk

dijk

v ec

to

rvector

vector

建圖,過 6

66 組。

//tle

#include

using namespace std;

typedef

long

long ll;

typedef pairint>p;

const ll inf=

0x3f3f3f3f3f3f3f3f

;const

int maxn=

2e4+10;

const

int maxm=

6e4+10;

int head[maxn]

,cnt,from[maxm]

,to[maxm]

;int n,m;

ll dis[maxn]

,cost[maxm]

;struct edgeedge[maxm]

;void

addedge

(int u,

int v,ll w)

void

dijk

(int s)}}

}int

main()

dijk(1

); ll ans=0;

for(

int i=

1;i<=n;i++

) ans+

=dis[i]

; cnt=0;

for(

int i=

1;i<=n;i++

) head[i]=-

1;for(

int i=

1;i<=m;i++

)addedge

(to[i]

,from[i]

,cost[i]);

dijk(1

);for(

int i=

1;i<=n;i++

) ans+

=dis[i]

;printf

("%lld\n"

,ans);}

return0;

}

最短路徑中的反向建邊

我們很容易理解並且處理單源最短路,從某點a出發,到達終點b的最短路徑,為了到達終點,我們不可避免的就需要經過每乙個點 鬆弛操作 那麼如果由多個終點到達某乙個點,那麼我們需要把很多次dijkstra或者spfa嗎,或者說直接來乙個floyd 前提是點數很少,畢竟o n 3 那麼我們就可以反向建邊來很快...

最短路SPFA演算法(解決負權邊)

演算法思想 實現方法 建立乙個佇列,初始時佇列裡只有起始點,再建立乙個 記錄起始點到所有點的最短路徑 該 的初始值要賦為極大值,該點到他本身的路徑賦為0 然後執行鬆弛操作,用佇列裡有的點作為起始點去重新整理到所有點的最短路,如果重新整理成功且被重新整理點不在佇列中則把該點加入到佇列最後。重複執行直到...

單源負邊最短路演算法 Spfa

求單源最短路的spfa演算法的全稱是 shortest path faster algorithm。很多時候,給定的圖存在負權邊,這時類似dijkstra等演算法便沒有了用武之地,而bellman ford演算法的複雜度又過高,spfa演算法便派上用場了。有人稱spfa演算法是最短路的萬能演算法。簡...