週末訓練 逛公園

2021-09-29 06:29:12 字數 3745 閱讀 7911

【記憶體限制:$512mib$】【時間限制:$3000ms$】

【標準輸入輸出】

【題目型別:傳統】【評測方式:文字比較】

策策每天都會去逛公園,他總是從$1$號點進去,從$n$號點出來。

策策喜歡新鮮的事物,他不希望有兩天逛公園的路線完全一樣,同時策策還是乙個特別熱愛學習的好孩子,他不希望每天在逛公園這件事上花費太多的時間。如果$1$號點到$n$號點的最短路長為$d$,那麼策策只會喜歡長度不超過$d+k$的路線。

策策同學想知道總共有多少條滿足條件的路線,你能幫幫他嗎?

為避免輸出過大,答案對$p$取模。

如果有無窮多條合法的路線,請輸出$-1$。

第一行包含乙個整數$t$, 代表資料組數。

接下來$t$組資料,對於每組資料:

第一行包含四個整數$n,m,k,p$, 每兩個整數之間用乙個空格隔開。

接下來$m$行,每行三個整數$a_i,b_i,c_i$, 代表編號為$a_i,b_i$的點之間有一條權值為$c_i$的有向邊,每兩個整數之間用乙個空格隔開。

輸出檔案包含$t$行,每行乙個整數代表答案。

樣例輸入

257

21012

1240

4522

3234

1352

1532

20101

2021

0

樣例輸出

3

-1

對於第一組資料,最短路為$3$。

$1-5,1-2-4-5,1-2-3-5$為$3$條合法路徑。

對於不同測試點,我們約定各種引數的規模不會超過如下

測試點編號

$t$$n$

$m$$k$

是否有$0$邊

$1$$5$

$5$$10$

$0$否

$2$$1000$

$2000$

$3$$50$

$4$$5$

$6$是

$7$$100000$

$200000$

$0$否

$8$$3$

$50$

$9$是

$10$

對於 $100\%$ 的資料:$1\le p \le 10^9,1 \le a_i,b_i \le n ,0 \le c_i \le 1000$。

資料保證:至少存在一條合法的路線。

剛開始想的是一遍$dij$跑出最短路,然後對於每一條在最短路上的點,用其他的一些邊來替換。

後來發現時間複雜度有點不可靠,大概是在$o(nm)$的範圍左右。

一道最短路+$dp$題。

先設最短路長度為$d$。

那麼我們要求的就是長度在$d+k$以內的路徑的數量。

首先,如果我們要把每一條路都求出來,那麼這是一定不可行的,因為這道題的資料範圍比較大。

那麼我們應該怎麼做這道題呢?

其實與我在做題的時候思路是比較靠近的,但是我想到的是將每一條邊進行替換,卻沒有想到直接進行距離的計算。

我們先將輸出$-1$的情況解決了。

其實很簡單,就是在某一條合法路徑上,有乙個$0$環(就是乙個環上所有的邊權值都為$0$),那麼就輸出$-1$。

這個情況很簡單,難點還是在計算總路徑數上。

首先建乙個逆圖,從終點開始跑一邊$dij$,得到每個點$u$到終點的最短距離$dis[u]$。

考慮邊$edge[i]=(u,v,w)$,從$u$到$v$。

現在開始處理第二種情況,如果$dis[u]+w-dis[v]≤k$,說明將從點$u$到點$v$的最短路徑直接替換為$edge[i]$是合法的,因為這條新的路徑與最短路的差即為從$u$到$v$的最短路徑的差,而我們又保證了這個差$x$是小於等於$k$的。

當然,如果$dis[u]+w-dis[v]>k$,說明替換後的路徑是不合法的,不用管即可。

但是如果我們將每次都存下來再計數,實際上是很費時間的,這個時候我們就要考慮記憶化(或者說是$dp$)。

令$dp[u][k]$:搜尋到點$u$的一條路徑上,其長度與路徑長度上界(即$d+k$)的差值為$k$時,總路徑的長度。

最後再整合一下**即可。

順帶提一句,注意每組資料的初始化。不然你就$wa$穿地球了

#includeusing

namespace

std;

template

inline void qread(t&x)

template

inline void qread(t& x,args&... args)

inline

intrqread()

template

inline t max(const t x,const t y)

template

inline t min(const t x,const t y)

template

inline t fab(const t x)

const

int maxm=200000

;const

int maxn=100000

;const

int maxk=50

;class

gragh

edge(

const

int t,const

int n,const

intw):to(t),nxt(n),w(w){}

}e[edge_size+5

];

int tail[node_size+5

],ind;

inline

void add_edge(const

int u,const

int to,const

int w)

inline

void dijkstra(int dis,const

int s,const

intn)

node(

const

int u,const

intw):u(u),w(w){}

};struct

cmp };

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

; priority_queue

,cmp>q;

q.push(node(s,dis[s]=0

));

while(!q.empty())

}inline

void clr()

gragh()

}g,rg;

intt,n,m,k,p,a,b,c;

int dis[maxn+5],dp[maxn+5][maxk+5

];bool

in[maxn+5][maxk+5

];int dfs(const

int u,const

intk)

return

in[u][k]=false

,dp[u][k];

}void

init()

signed main()

return0;

}

小白逛公園

描述 小新經常陪小白去公園玩,也就是所謂的遛狗啦 在小新家附近有一條 公園路 路的一邊從南到北依次排著n個公園,小白早就看花了眼,自己也不清楚該去哪些公園玩了。一開始,小白就根據公園的風景給每個公園打了分 小新為了省事,每次遛狗的時候都會事先規定乙個範圍,小白只可以選擇第a個和第b個公園之間 包括a...

小白逛公園

小白逛公園 time limit 20000ms memory limit 65536k case time limit 2000ms description 小新經常陪小白去公園玩,也就是所謂的遛狗啦 在小新家附近有一條 公園路 路的一邊從南到北依次排著n個公園,小白早就看花了眼,自己也不清楚該去...

嘟嘟逛公園

一道dp題目 題目題目描述 小欣有乙隻可愛的小狗,名字叫嘟嘟,晚飯後她倆經常外出散步。小欣家附近有一條 公園路 路的一邊從東到西依次排著n個公園,有時她倆從東向西散步,有時從西向東散步。一開始,嘟嘟根據公園的風景給每個公園打了分。小欣為了省事,每次遛狗都會事先規定乙個範圍,嘟嘟只能選擇第a個和第b個...