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