NOIp2017 逛公園 dp 記搜

2022-04-28 19:30:10 字數 2268 閱讀 1426

給定乙個有向圖,起點為\(1\),終點為\(n\),求和最短路相差不超過\(k\)的路徑數量.有\(0\)邊.如果有無數條,則輸出\(-1\).

\(n\leq 10^5,k\leq 50\)

首先,有無數條邊的情況一定是在與最短路相差不超過\(k\)的一條路上有\(0\)環.

先不考慮\(0\)邊和\(0\)環,\(get\ 70pts\)做法:先跑乙個最短路,\(dis[i]\)表示從\(1\)到\(i\)的最短路徑.記\(f[u][k]\)表示從\(1\)到\(u\)路徑長度不超過\(dis[u]+k\)的路徑條數,\(f[u][k]\)顯然是轉移到\(f[v][dis[u]+k+w(u,v)-dis[v]]\).轉移順序顯然是從\(dis\)小的轉移到\(dis\)大的,直接按\(dis\)從小到大的順序.於是乙個\(o(nk)\)的\(dp\)就出爐了.

考慮正解.

首先看怎麼判斷無窮解.記\(f_i\)為\(1\)到\(i\)的最短路,\(g_i\)為\(i\)到\(n\)的最短路.判斷無窮解:先把所有可行的\(0\)邊拎出來,再看它們是不是組成了環.一條邊\((i,j)\)可行當且僅當\(f_i+g_j+w\leq f_n+k\).於是這裡就可以簡單判斷了.

接下來仍然是\(dp\),但是因為\(0\)邊的存在所以並不能直接按\(dis\)從小到大的順序轉移,我們需要另外一種方法來確定\(0\)邊兩個端點的轉移順序.考慮把所有可行的\(0\)邊的兩個端點拎出來,然後拓撲排序.最後對於所有的點,只需要按照\(f\)為第一關鍵字,拓撲排序排出來的順序為第二關鍵字排序,按照這個順序更新即可.

其實還有更加簡單的記憶化搜尋的寫法:

\(dfs(u,res)\)表示已經從\(1\)號結點跑到\(u\)結點,還有可以比最短路多走\(res\)的長度,走到\(n\)結點的方案數.顯然這裡需要跑乙個反向最短路\(dis\).答案是\(\sum dfs(v,res-(dis_v+w-dis_u))\).記憶化一下即可.

怎麼判斷\(0\)環呢?只需要記乙個\(stk_\)表示在搜尋樹中當前結點的祖先結點們有沒有出現過這個狀態,如果有,那麼就一定有\(0\)環.

我永遠喜歡記搜!

對了,還看到乙個非常神仙的分層圖求法.在這裡.

#include#define il inline

#define ri register int

#define go(i,a,b) for(ri i=a;i<=b;++i)

#define yes(i,a,b) for(ri i=a;i>=b;--i)

#define e(i,u) for(ri i=b[u];i;i=a[i].nt)

#define mem(a,b) memset(a,b,sizeof(a))

#define ll long long

#define db double

#define inf 2147480000

#define pr pair#define mp make_pair

#define fi first

#define sc second

using namespace std;

il int read()

while(c>='0'&&c<='9')

return x*y;

}const int n=1e5+5;

int n,m,k,p,b[n],ct,dis[n],as,rem[n][55];

bool fl,stk[n][55];

priority_queueq;

struct nda[n*2];

struct ede[n*2];

il void add(ri u,ri v,ri w);b[u]=ct;}

il void inc(ri &x,ri y)

il void dijkstra()

stk[u][res]=0;return rem[u][res]=ret;

}int main()

; mem(b,0);ct=0;

go(i,1,m)add(e[i].v,e[i].u,e[i].w);

dijkstra();

mem(b,0);ct=0;

go(i,1,m)add(e[i].u,e[i].v,e[i].w);

mem(stk,0);mem(rem,0);rem[n][0]=1;

go(i,0,k)

if(fl)printf("-1\n");

else printf("%d\n",as);

}return 0;

}

NOIP 2017 逛公園 最短路 dp

題意 求出 從 1 到 n 的路徑長度小於等於最短路 k 的路徑個數 分析 首先觀察資料特點 30 的資料 k 0 且沒有 0 邊,等同於最短路計數 70 的資料沒有 0 邊,那麼就是相當於沒有 0 環 100 的資料 k le 50 首先考慮第一檔 顯然就是乙個最短路徑計數,是乙個非常經典的問題,...

比賽 NOIP2017 逛公園

考試的時候靈光一閃,瞬間推出dp方程,但是不知道怎麼判 1,然後?然後就炸了。後來發現,我只要把拓撲和dp分開,中間加乙個判斷,就ac了,可惜。看這道題,我們首先來想有哪些情況是 1 只要有零環在滿足題目要求的路徑上,那麼這條路徑就可以不停地走,於是就 1了。如何判有沒有零環呢?機械化地兩遍不同方向...

NOIP2017 洛谷 逛公園

初見安 這個本狸咕了4個月的題終於寫出來了qaq!這裡是傳送門 洛谷p3953 逛公園 策策每天都會去逛公園,他總是從1號點進去,從nn號點出來。策策喜歡新鮮的事物,它不希望有兩天逛公園的路線完全一樣,同時策策還是乙個 特別熱愛學習的好孩子,它不希望每天在逛公園這件事上花費太多的時間。如果1號點 到...