給你四個點,相鄰兩個點之間有一條連邊。現在問你從$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 能被湊出當且僅當...