肯定要先跑一次最短路
題目中的k 相當於允許我們走k距離的「冤枉路」
回想之前有些題是如何判斷哪些邊是屬於最短路上的 當dis[now]+edge[u].val==dis[vis] 這條邊就在最短路上
類似的 我們可以得出 dis[now]+edge[u].val-dis[vis]就是這一次走的「冤枉路」的長度
到這個地方搜尋的策略已經很明顯了 dfs(now,remain)表示當前當前點為now 還剩remain的冤枉路可以走
邊界條件:remain<0
然後發現這玩意兒不用標記vis陣列 因為就算有環 remain會一直減下去直到<0 還可以記憶化一下
不過無窮多的情況腫麼判?
可以這樣想 為什麼資料會給你有沒有0邊?
回憶最短路計數就會問你有沒有無窮多條滿足要求的路 這種情況只有可能是有0環存在
在這道題裡判0環異常容易 假如進入了0環 那肯定會繞了一圈後 又回到當前點 且remain不變
因此標記一下就好
另外 還有乙個坑點 這是有向圖 很有可能有些點無法到達終點
因此還要反向搜出那些不能到達的
#include#define n 100005#define m 200005
#define inf 0x3f3f3f3f
using namespace std;
templateinline void read(t &x)
struct edge
edge[2*m];
struct node };
int n,m,k,p,tot,first[n],dis[n];
inline void addedge(int x,int y,int z)
vectorres[n];
typedef pairpair;
bool visit[n],able[n];
void dijkstra(int s)
{ memset(dis,0x3f,sizeof(dis));
memset(visit,false,sizeof(visit));
priority_queue,greater> heap;
heap.push(make_pair(0,s)); dis[s]=0;
while(!heap.empty())
{int now=heap.top().second;
heap.pop();
if(visit[now]) continue;
visit[now]=true;
for(int u=first[now];u;u=edge[u].next)
{int vis=edge[u].to;
if(dis[now]+edge[u].val
NOIP 2017 逛公園 最短路 dp
題意 求出 從 1 到 n 的路徑長度小於等於最短路 k 的路徑個數 分析 首先觀察資料特點 30 的資料 k 0 且沒有 0 邊,等同於最短路計數 70 的資料沒有 0 邊,那麼就是相當於沒有 0 環 100 的資料 k le 50 首先考慮第一檔 顯然就是乙個最短路徑計數,是乙個非常經典的問題,...
NOIp2017 逛公園 dp 記搜
給定乙個有向圖,起點為 1 終點為 n 求和最短路相差不超過 k 的路徑數量.有 0 邊.如果有無數條,則輸出 1 n leq 10 5,k leq 50 首先,有無數條邊的情況一定是在與最短路相差不超過 k 的一條路上有 0 環.先不考慮 0 邊和 0 環,get 70pts 做法 先跑乙個最短路...
比賽 NOIP2017 逛公園
考試的時候靈光一閃,瞬間推出dp方程,但是不知道怎麼判 1,然後?然後就炸了。後來發現,我只要把拓撲和dp分開,中間加乙個判斷,就ac了,可惜。看這道題,我們首先來想有哪些情況是 1 只要有零環在滿足題目要求的路徑上,那麼這條路徑就可以不停地走,於是就 1了。如何判有沒有零環呢?機械化地兩遍不同方向...