Luogu P3953 逛公园
不管怎么說,這都是一道十分神仙的NOIp題
你可以說它狗,但不可以否認它就是NOIp的難度
首先這道題很顯然是道圖論題還是一道圖論三合一(最短路+拓撲+圖上DP)
先考慮最短路,我們分別以\(1\)和\(n\)為起點得出與其它點的最短路(雖然NOIp應該不會卡SPFA,但還是建議寫穩定的DJ)
我們先考慮把\(-1\)的情況給判掉,分析一下發現此時必定有0環(此時可以在0環上無限刷路徑)
但是要注意一下,當且僅當0環上的任意一點\(i\)到\(1\)的最短路\(dis_{1,i}\)以及它到\(n\)的最短路\(dis_{i,n}\)滿足\(dis_{1,i}+dis_{i,n}<=dis_{1,n}+k\),因為這個0環首先得在可行路徑上
處理0環的具體操作只要把0邊權的邊單獨拎出來做拓撲排序就好了。
然后考慮如何統計答案,我們發現\(k<=50\)。因此我們圖上DP計數。
設\(f_{i,j}\)表示到第\(i\)個點時,偏移量(偏移量為當前路徑長度與\(dis_{1,i}\)的差)為\(j\)的方案數:
我們再枚舉\(i\)可以到達的點\(p\),若\(dis_{1,i}+w+j-dis_{1,p}<=k\),然后就可以用\(f_{i,j}\)更新\(f_{p,dis_{1,i}+w+j-dis_{1,p}}\)了(\(w\)為\(i\rightarrow p\)的邊權)
最后要注意的是枚舉的狀態順序,我們發現對于所有的點\(i\),當它的\(dis_{1,i}\)越小時,它越早更新
特別地,當都是0權的邊排序時,應該按之前的拓撲順序排
CODE
#include<cstdio> #include<cctype> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=100005,K=55; struct edge {int to,next,v; }e[N<<1],re[N<<1]; struct Zero_edge {int to,next; }ze[N<<1]; struct Small {int num,s;bool operator <(const Small x) const { return x.s<s; } }; struct data {int d,id,num; }a[N]; int head[N],rhead[N],zhead[N],t,n,m,k,p,x,y,z,cnt,zcnt,ru[N],q[N],f[N][K],dis[N],INF,r[N]; bool vis[N]; priority_queue <Small> small; inline char tc(void) {static char fl[100000],*A=fl,*B=fl;return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++; } inline void read(int &x) {x=0; char ch; while (!isdigit(ch=tc()));while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc())); } inline void write(int x) {if (x>9) write(x/10);putchar(x%10+'0'); } inline void clear(void) {memset(head,-1,sizeof(head)); memset(rhead,-1,sizeof(rhead));memset(zhead,-1,sizeof(zhead)); memset(ru,0,sizeof(ru)); cnt=zcnt=0; } inline void add(int x,int y,int z) {e[++cnt].to=y; e[cnt].next=head[x]; e[cnt].v=z; head[x]=cnt; } inline void radd(int x,int y,int z) {re[cnt].to=y; re[cnt].next=rhead[x]; re[cnt].v=z; rhead[x]=cnt; } inline void zadd(int x,int y) {ze[++zcnt].to=y; ze[zcnt].next=zhead[x]; zhead[x]=zcnt; ++ru[y]; } inline void top_sort(void) {register int i,H=0,T=0;for (i=1;i<=n;++i){if (!ru[i]) q[++T]=i,a[i].id=T; a[i].num=i;}while (H<T){int now=q[++H];for (i=zhead[now];~i;i=ze[i].next)if (!(--ru[ze[i].to])) q[++T]=ze[i].to,a[ze[i].to].id=T;} } inline void front_dijkstra(void) {memset(dis,63,sizeof(dis)); memset(vis,0,sizeof(vis));small.push((Small){1,0}); INF=dis[0]; dis[1]=a[1].d=0;while (!small.empty()){int now=small.top().num; small.pop();if (vis[now]) continue; vis[now]=1;for (register int i=head[now];~i;i=e[i].next)if (dis[e[i].to]>dis[now]+e[i].v){a[e[i].to].d=dis[e[i].to]=dis[now]+e[i].v;small.push((Small){e[i].to,dis[e[i].to]});}} } inline void back_dijkstra(void) {memset(dis,63,sizeof(dis)); memset(vis,0,sizeof(vis));small.push((Small){n,0}); dis[n]=0;while (!small.empty()){int now=small.top().num; small.pop();if (vis[now]) continue; vis[now]=1;for (register int i=rhead[now];~i;i=re[i].next)if (dis[re[i].to]>dis[now]+re[i].v){dis[re[i].to]=dis[now]+re[i].v;small.push((Small){re[i].to,dis[re[i].to]});}} } inline bool check(void) {for (register int i=1;i<=n;++i)if (ru[i]&&a[i].d+dis[i]<=a[n].d+k) return 1;return 0; } inline bool cmp(data a,data b) {if (a.d<b.d) return 1;if (a.d>b.d) return 0;return a.id<b.id; } inline void inc(int &x,int y) {if ((x+=y)>=p) x-=p; } inline int DP(void) {memset(f,0,sizeof(f)); f[1][0]=1; int ans=0;for (register int s=0;s<=k;++s){for (register int i=1;i<=n;++i){int now=a[i].num;for (register int j=head[now];~j;j=e[j].next)if (a[i].d+s+e[j].v-a[r[e[j].to]].d<=k) inc(f[e[j].to][a[i].d+s+e[j].v-a[r[e[j].to]].d],f[now][s]);}inc(ans,f[n][s]);} return ans; } int main() {//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);register int i; read(t);while (t--){read(n); read(m); read(k); read(p); clear();for (i=1;i<=m;++i){read(x); read(y); read(z);add(x,y,z); radd(y,x,z); if (!z) zadd(x,y);}top_sort(); front_dijkstra(); back_dijkstra();if (check()) { puts("-1"); continue; } sort(a+1,a+n+1,cmp);for (i=1;i<=n;++i) r[a[i].num]=i;write(DP()); putchar('\n');}return 0; }轉載于:https://www.cnblogs.com/cjjsb/p/9337052.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Luogu P3953 逛公园的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: qt5.10 for android 使
- 下一篇: 洛谷 P2921 [USACO08DEC