HDU 6071(同餘最短路)

2022-07-13 09:57:06 字數 1501 閱讀 9798

給你四個點,相鄰兩個點之間有一條連邊。現在問你從$2$號點走到$2$號點的至少為$k$的最短路的長度。

因為題目中的$k$比較大,因此一些亂搞的演算法顯然無法通過,而鑑於點數相對來說比較少,因此我們得研究一下這幾個點所蘊涵的性質。

我們發現,對於$2$號結點,它有兩條可行的邊,我們設這兩條邊的距離分別為$d_$以及$d_$,其中最小的邊為$w$,(即$w=\min(d_,d_)$)。如果要從$2$號結點走回到$2$號結點,乙個顯然優的策略是我們至少要訪問兩次$w$邊。即答案至少為$2*w$。

假設我們當前從$2$到$2$的最短路為$d_i$,則我們顯然可以進行$t$次上述的操作,使得最終的答案滿足$d_i+2*t*w \ge k$。顯然這是乙個線性的方程組,引數為$d_i$以及$t$。而我們要知道$t$的大小,顯然只需要知道$d_i \%2w$的值即可。

因此,這個問題其實是乙個線性同餘的問題,因為最終的答案跟$d_i \%2w$有關,我們可以設$dis[i][j]$,為從起點到$i$點,最短路徑$\%2w$餘$j$的最短路長度。此時的狀態數就直接被我們縮短為$2*w*4$個,因此此時我們直接可以用最短路演算法去求解了。

最後我們只需要不斷列舉$dis[2][j]$,判斷求出最優的$t$以及$d_i$即可

時間複雜度:$\mathcal(wlogw)$

#include

#define maxn 10

using

namespace std;

typedef

long

long ll;

typedef pairint>pll;

struct nodeq[10]

;const ll inf=

0x3f3f3f3f3f3f3f3f

;int head[maxn]

,cnt=0;

ll dis[10]

[100005

],d;

void

add_edge

(int from,

int to,

int cost)

void

dijk

(int x)

dis[x][0

]=0;

que.

push

(pll

(0ll

,x))

;while

(!que.

empty()

)}}}

int val[10]

;int

main()

for(

int i=

1;i<=

4;i++

) d*=2

;dijk(2

);ll minn=inf;

for(

int i=

0;i<=d;i++

)else

}printf

("%lld\n"

,minn);}

return0;

}

hdu6071 最短路 解不等式 2017多校4

求出所有,從2走到x所需的花費在對 t 2 min d1,2,d2,3 模運算下,所有剩餘系的最短路即可 把乙個點拆成 t 個點,每個點代表一種剩餘系 知道了所有剩餘系就可以湊出答案。dis 2 0 到 dis 2 t 1 代表的即為對 t 取模的所有剩餘系的最短路 假設任意路線走回 2 點的話費是...

同餘最短路小記

前幾天 mns 的時候遇到被卡科技了,然後墊底了 雖說是個極其簡單的東西,但是出於學乙個演算法必須要寫學習筆記的強迫症,還是寫幾行字吧。考慮問題 給定正整數 a 有哪些非負整數能被 a 由非負整數權線性表出。n 2 exgcd?完全揹包?我們發現若 x 可以,則 x ka 1 k in n 也可以。...

演算法模版 同餘最短路

當我們解決形如 sum n a ix i k 的時候,我們可以使用同餘最短路來解決。我們選擇乙個最小的 a i 作為base,然後把其他的 a 表示成 base p left 的形式。我們定義 f i 代表湊出 bmod base 餘 i 的數最小需要多少個 base 而乙個數 p 能被湊出當且僅當...