高手訓練 最短路 負環 記錄

2021-10-05 08:32:17 字數 3259 閱讀 2330

設dis

[k][

i][j

]dis[k][i][j]

dis[k]

[i][

j]表示從點i

ii走到點j

jj走了2

k2^k

2k條邊的最短路徑長度。

a sd

[i][

j]

asd[i][j]

asd[i]

[j]表示二分到當前答案時點i

ii到點j

jj的最短路。

d is

[k][

i][j

]dis[k][i][j]

dis[k]

[i][

j]用f lo

ydo(

n3

log⁡n)

floyd\ o(n^3\log n)

floydo

(n3logn)

預處理對於任意乙個正整數x

xx,它顯然可以被表示成2

22的整數次冪的和。

所以可以從大到小列舉k

kk,每次用dis

[k][

i][j

]dis[k][i][j]

dis[k]

[i][

j]去更新asd

[i][

j]

asd[i][j]

asd[i]

[j]。表示從點i

ii到點j

jj的路徑上常識一次走2

k2^k

2k條邊qwe

[i][

j]=m

in(q

we[i

][j]

,min

(dis

[z][

i][k

]+as

d[k]

[j],

dis[

z][k

][j]

+asd

[i][

k]))

qwe[i][j]=min(qwe[i][j],min(dis[z][i][k]+asd[k][j],dis[z][k][j]+asd[i][k]))

qwe[i]

[j]=

min(

qwe[

i][j

],mi

n(di

s[z]

[i][

k]+a

sd[k

][j]

,dis

[z][

k][j

]+as

d[i]

[k])

) 此處需要另外開乙個陣列qwe

qweqw

e來儲存更新的結果,如果直接在原asd

asdas

d陣列上更新會導致asd

[i][

j]

asd[i][j]

asd[i]

[j]又被剛更新完的asd

[i][

z],a

sd[z

][j]

asd[i][z],asd[z][j]

asd[i]

[z],

asd[

z][j

]更新,這樣的話一次就不止嘗試走2

k2^k

2k步了。更新後列舉原圖的某一條邊,如果存在wi+

qwe[

ui][

vi

]<

0w_i+qwe[u_i][v_i]<0

wi​+qw

e[ui

​][v

i​]<

0,則原圖存在負環。

當前答案肯定大於最終答案,否則要把asd

asdas

d陣列賦成更新後的qwe

qweqw

e,把答案加上2

k2^k

2k但是此做法是有點問題的,從點i

ii到點j

jj走k

kk條邊的最短路不一定大於等於走k+1

k+1k+

1條邊的最短路,即不滿足單調性

對此有乙個巧妙的方法就是給每個點加一條長度為0

00的自環即可,這樣對答案沒有影響

複雜度o(n

3log⁡n

)o(n^3\log n)

o(n3

logn)

code:

#include

using

namespace std;

#define f1(a,b,c) for(int c=a;c<=b;c++)

#define f2(a,b,c) for(int c=a;c>=b;c--)

#define f3(a,b,c) for(int c=a;c;c=b)

#define so1(a,n) sort(a+1,a+n+1,mycmp);

#define so2(a,n) sort(a+1,a+n+1);

#define ll long long

#define itn int

#define ubt int

#define mp make_pair

#define pii pair

#define pll pair

const

int twx=

300+

100;

const

int inf=

0x3f3f3f3f

;ll read()

c=getchar()

;}while

(c>=

'0'&&c<=

'9')

return sum*flag;

}int n;

int m;

int dis[15]

[twx]

[twx]

;int asd[twx]

[twx]

;int qwe[twx]

[twx]

;int ans=0;

void

init()

}void

work()

f1(0,

8,z)}}

}f1(1

,n,i)f2(

8,0,z)}f1

(1,n,k)}}

int flag=0;

f1(1,n,i)}if

(!flag)}}

}}void

print()

intmain()

最短路專題 spfa判斷負環

題目大意 有多種匯幣,匯幣之間可以交換,這需要手續費,當你用100a幣交換b幣時,a到b的匯率是29.75,手續費是0.39,那麼你可以得到 100 0.39 29.75 2963.3975 b幣。問s幣的金額經過交換最終得到的s幣金額數能否增加 貨幣的交換是可以重複多次的,如果有乙個環使得某種貨幣...

最短路判負環uva11090

這道題注意輸出格式是 劉汝佳上的原題不解釋。no circle found.而不是no circle found 還容易出錯的地方1.陣列大小2.變數的型別 是否會超出變數表示範圍 3.邊界條件。此題我覺得是應該有負邊但很顯然沒有相應的測試樣咧 我用別人有bug的 交過。include includ...

演算法訓練 最短路

問題描述 給定乙個n個頂點,m條邊的有向圖 其中某些邊權可能為負,但保證沒有負環 請你計算從1號點到其他點的最短路 頂點從1到n編號 輸入格式 第一行兩個整數n,m。接下來的m行,每行有三個整數u,v,l,表示u到v有一條長度為l的邊。輸出格式 共n 1行,第i行表示1號點到i 1號點的最短路。樣例...