NOIP2017逛公園(park)解題報告

2022-05-25 13:54:10 字數 1667 閱讀 6641

park作為今年noipday1最後一道題還是相比前面幾道題還是有點難度的

首先你可以思考一下,第一天dp不見了,再看一下這題,有向圖,看起來就比較像乙個dp,考慮dp方程,首先肯定有一維是到哪個節點,還有一維肯定與路徑長度有關,顯然第二位就記錄超過最短路多少。

這樣我們可以找到dp方程,首先列舉乙個kk(0<=kk<=k),按拓撲序列舉每乙個點,列舉以這個點為起點的路徑,如果這條路在最短路上,那麼dp[v][kk]+=dp[u][kk],else 如果dis[u]+kk+路徑長度<=dis[v]+k則也可以進行類似的轉移

首先我們先正著跑一遍spfa,再反著跑一遍,以為要判斷乙個點在不在最短路上,只需要看起點到它的最短路+終點到它的最短路之和是否等於起點到終點的最短路

接下來如果這條邊在最短路上則這條路終點入度+1,再拓撲排序一遍順便檢查出有無0環,接下來就可以dp了

接下來看**吧

#includeusing namespace std;

typedef int sign;

typedef long long ll;

#define for(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)

#define fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)

const int n=1e5+5;

bool cmax(sign &a,sign b)

templatet read()

void file()

int dis[n][2],in[n];

int n,m,k,p;

struct graph

inline void add(int x,int y,int z)

}g[2];//因為雙向建圖,所以寫在結構體裡

#define tra(g,i,u) for(register int i=g.head[u];i;i=g.nex[i])

bool vis[n];

inline void input()

}queueq;

inline void spfa(int st,int now)}}

}}//跑spfa,因為要跑兩遍,所以0表示正著的,1表示反著的

int l[n];

bool check()}}

for(i,1,n)if(in[i]&&dis[i][0]+dis[i][1]<=dis[n][0]+k)return 1;

//如果在最短路上且有環,則說明有0環

return 0;

}int dp[n][55];

inline void add(int &a,int b)

inline void topsort()}}

}int ans=0;

for(i,0,k)add(ans,dp[n][i]);

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

}inline void work()

}if(check())

topsort();

}const int inf=0x3f3f3f3f;

inline void init()

int main()

return 0;

}

比賽 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 做法 先跑乙個最短路...