【記憶體限制:$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$行,每行乙個整數代表答案。
樣例輸入
25721012
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$穿地球了
#includeusingnamespace
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個...