洛谷 P3953 [NOIP2017 提高組] 逛公園(最短路,記憶化搜尋)
阿新 • • 發佈:2021-06-20
傳送門
解題思路
令 \(dp[i][j]\) 表示從 \(1\) 號點到 \(i\) 號點的長度比最短路多 \(j\) 的路徑的條數。
則答案為:
從 \(n\) 開始在反圖上進行轉移,轉移方程為:
\[dp[u][k]=\sum dp[v][k-(value-(dis[u]-dis[v]))] \]其中 \(v\) 為 \(u\) 的子節點,\(value\) 為邊權,\(dis[i]\) 為 \(1\) 號點到 \(i\) 號點的最短路長度。
初始化:\(dp[1][0]=1\)
判斷是否經過零環:若求解某個dp值時有用到了此dp值,則必有零環。
AC程式碼
#include<cstdio> #include<iostream> #include<cstring> #include<iomanip> #include<cmath> #include<algorithm> #include<queue> using namespace std; const int maxn=100005; int T,n,m,mod,k,dp[maxn][55],dis[maxn],p[maxn],P[maxn],cnt1,cnt2; int on[maxn],in[maxn],vis[maxn][55],wrong; struct node{ int u,v,w,next; }e[maxn*2],E[maxn*2]; void insert1(int u,int v,int w){ cnt1++; e[cnt1].u=u; e[cnt1].v=v; e[cnt1].w=w; e[cnt1].next=p[u]; p[u]=cnt1; } void insert2(int u,int v,int w){ cnt2++; E[cnt2].u=u; E[cnt2].v=v; E[cnt2].w=w; E[cnt2].next=P[u]; P[u]=cnt2; } void dfs1(int u){ on[u]=1; for(int i=p[u];i!=-1;i=e[i].next){ int v=e[i].v; if(on[v]) continue; dfs1(v); } } void spfa(){ memset(dis,0x3f,sizeof(dis)); memset(in,0,sizeof(in)); queue<int> q; in[1]=1; dis[1]=0; q.push(1); while(!q.empty()){ int u=q.front(); q.pop(); in[u]=0; for(int i=p[u];i!=-1;i=e[i].next){ int v=e[i].v; if(dis[v]>dis[u]+e[i].w){ dis[v]=dis[u]+e[i].w; if(!in[v]){ q.push(v); in[v]=1; } } } } } int dfs(int u,int now){ if(now<0) return 0; if(vis[u][now]){ wrong=1; return dp[u][now]=0; } if(dp[u][now]!=-1) return dp[u][now]; dp[u][now]=0; vis[u][now]=1; for(int i=P[u];i!=-1;i=E[i].next){ int v=E[i].v; if(!on[v]) continue; dp[u][now]=(dp[u][now]+dfs(v,now-(E[i].w-(dis[u]-dis[v]))))%mod; } vis[u][now]=0; if(u==1&&now==0) dp[u][now]=1; return dp[u][now]; } void work(){ dfs1(1); spfa(); int ans=0; wrong=0; for(int i=0;i<=k;i++){ ans=(ans+dfs(n,i))%mod; if(wrong==1){ printf("-1\n"); return; } } printf("%d\n",ans); } int main(){ cin>>T; while(T--){ memset(on,0,sizeof(on)); memset(p,-1,sizeof(p)); memset(P,-1,sizeof(P)); memset(dp,-1,sizeof(dp)); cnt1=cnt2=0; cin>>n>>m>>k>>mod; for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); insert1(u,v,w); insert2(v,u,w); } work(); } return 0; }
//NOIP2017提高組Day1 t3