NOIP2017tg 逛公園 題解

2022-05-25 13:00:24 字數 1976 閱讀 8800

emmm……,這是本蒟蒻的第一篇題解,大佬們勿噴qwq(要不是看到寫題解可以加貢獻,我才……)

可以看到標籤,是2023年提高的題目,好像是day1t3,感覺提高考這樣的題目挺好的,至少考場上也可以很快想到做法。唉……,我太菜了,調這道題調了一下午才滿,要是在考場上肯定死。

看了題解幾位奆佬的思路,有拓撲的,記憶化搜尋的,跑反圖的,感覺和自己想得不是很一樣,於是想講一下本蒟蒻寫這道題的思路。

1)此題不卡spfa!!!請spfa黨放心使用!!!

2)此題部份分給得很足,直接使用p1608路徑統計的方法可以過30分。

前置技能:

1、【模板】負環 &&spfa

2、dp

題意:應該很清楚了吧,求1至n的所有路徑中,小於等於dis[n]+k的路徑數,結果取膜p。注意,圖有可能會出現0邊和0環。

既然我們選擇做這道題,就要奔著滿分前進!

本蒟蒻選擇的做法是spfa加dp,看很多大佬都要加拓撲什麼的來確定dp更新順序判0環,不過本蒟蒻表示完全沒有必要,其實在跑spfa的過程中,我們就可以隨便把這些問題解決掉。

1、判0環

判0環和判負環其實差不多,只需要在spfa中加乙個判斷即可,但是,由於此題卡時間卡得很緊,所以我們機房某大佬教了我卡帶,這樣判0環聽說可以快很多。

if(dis[v]>=dis[u]+cost[i])
注意:spfa這裡需要把'>'改成">=",不然判不了0環

剩下的判0環方法就和判負環差不多,如果還不明白可以看**。(另外提供一種判0環方式,把0邊全部抽出來,然後判環,拓撲什麼的)

2、確定dp更新順序

這個其實也很簡單,我們不難發現,其實只有0邊兩個點的順序需要確定更新順序,其他只需要按dis從小到大的順序更新就可以了。於是我們在spfa中加乙個更新就可以了。

if(id[v]這樣即可確定dp更新順序。dp前先按dis為第一關鍵字,id為第二關鍵字排序即可。

3、dp

額……,講了怎麼久的dp更新順序,可能你們還不懂怎麼dp吧,我的dp方法和kelin大佬的一樣,都是f[i][j]表示1至i的路徑中,小於等於dis[i]+j的路徑數。

轉移也很簡單,只要(dis[u]+j+(u至v的長度)-dis[v]<=k)

那麼就將f[v][dis[u]+j+(u至v的長度)-dis[v]]+=f[u][j];

最後記得取mh!dp的更新順序記得按關鍵字排序啊。

還有,本蒟蒻由於dp學得不是很好,所以講得如果不懂的話,可以看**或者kelin大佬講的,我覺得他dp講得比我好啊qaq。

for(int k=0;k<=kk;k++) //dp }}

}

dp**如上,還是比較好想到的呢。

好了那麼思路也就差不多了,總體的難度其實不是很大,不過這樣寫的時間複雜度會比用拓撲的高,畢竟在找0環的時候比較耗時間,但是方法肯定是沒問題的,接下來來看全部**吧。

#include#define maxm 800000

#define maxn 400000

#define inf 20010100

using namespace std;

int cnt,from[maxm],to[maxm],cost[maxm],next[maxm],head[maxm],cont[maxm],cb[maxn],id[maxn];//嗯,定義有點醜蛤

int dis[maxn],vis[maxn],f[maxn][65],ans;

int n,m,x,y,z,mod,kk;

struct kkka[maxn];

queueq;

int cmp(kkk a,kkk b)}}

}for(int i=0;i<=kk;i++)

ans+=f[n][i],ans%=mod; //最後統計答案

printf("%d\n",ans);

}}

比賽 NOIP2017 逛公園

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

NOIP2017 洛谷 逛公園

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

NOIp2017 逛公園 dp 記搜

給定乙個有向圖,起點為 1 終點為 n 求和最短路相差不超過 k 的路徑數量.有 0 邊.如果有無數條,則輸出 1 n leq 10 5,k leq 50 首先,有無數條邊的情況一定是在與最短路相差不超過 k 的一條路上有 0 環.先不考慮 0 邊和 0 環,get 70pts 做法 先跑乙個最短路...