1. 程式人生 > >luogu3563 逛公園

luogu3563 逛公園

queue printf span source main math cnblogs build 效率

兩遍 spfa 然後建立分層圖拓撲排序 dp 一下。
寫得很差勁。效率很低。
時間復雜度 \(\mathrm{O}(Tnk)\)
參見這裏秒懂。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
int T, n, m, k, p, cnt[2], hea[2][100005], dis[2][100005], uu, vv, ww, he[5100005], cn, dp[5100005];
int ind[5100005], f[100005][55
]; bool vis[5100005]; queue<int> d; struct Edge{ int too, nxt, val; }edge[2][200005], edg[10200005]; void rn(int &x){ char ch=getchar(); x = 0; while(ch<‘0‘ || ch>‘9‘) ch = getchar(); while(ch>=‘0‘ && ch<=‘9‘){ x = x * 10 + ch - ‘0‘; ch = getchar(); } } void
add_edge(int rr, int fro, int too, int val){ edge[rr][++cnt[rr]].nxt = hea[rr][fro]; edge[rr][cnt[rr]].too = too; edge[rr][cnt[rr]].val = val; hea[rr][fro] = cnt[rr]; } void add_edg(int fro, int too){ edg[++cn].nxt = he[fro]; edg[cn].too = too; he[fro] = cn; } void init(){ rn(n); rn(m); rn(k); rn(p); memset(he, 0
, sizeof(he)); memset(dp, 0, sizeof(dp)); memset(hea, 0, sizeof(hea)); memset(vis, 0, sizeof(vis)); memset(ind, 0, sizeof(ind)); memset(dis, 0x3f, sizeof(dis)); dis[0][1] = dis[1][n] = cnt[0] = cnt[1] = cn = 0; dp[1] = 1; for(int i=1; i<=m; i++){ rn(uu); rn(vv); rn(ww); add_edge(0, uu, vv, ww); add_edge(1, vv, uu, ww); } int qwq=0; for(int i=1; i<=n; i++) for(int j=0; j<=k; j++) f[i][j] = ++qwq; } void spfa(int rr){ d.push(rr?n:1); vis[rr?n:1] = true; while(!d.empty()){ int x=d.front(); d.pop(); vis[x] = false; for(int i=hea[rr][x]; i; i=edge[rr][i].nxt){ int t=edge[rr][i].too; if(dis[rr][t]>dis[rr][x]+edge[rr][i].val){ dis[rr][t] = dis[rr][x] + edge[rr][i].val; if(!vis[t]){ vis[t] = true; d.push(t); } } } } } void build(){ for(int i=1; i<=n; i++) for(int j=0; j<=k; j++) if(dis[0][i]+dis[1][i]+j<=dis[0][n]+k) vis[f[i][j]] = true; for(int i=1; i<=n; i++) for(int j=0; j<=k; j++) if(vis[f[i][j]]) for(int l=hea[0][i]; l; l=edge[0][l].nxt){ int t=edge[0][l].too, v=j+dis[0][i]+edge[0][l].val-dis[0][t]; if(v<=k && f[t][v]){ add_edg(f[i][j], f[t][v]); ind[f[t][v]]++; } } } void topsort(){ for(int i=1; i<=n; i++) for(int j=0; j<=k; j++) if(vis[f[i][j]] && !ind[f[i][j]]) d.push(f[i][j]); while(!d.empty()){ int x=d.front(); d.pop(); for(int i=he[x]; i; i=edg[i].nxt){ int t=edg[i].too; ind[t]--; if(ind[t]==0) d.push(t); dp[t] = dp[t]+dp[x]>=p?dp[t]+dp[x]-p:dp[t]+dp[x]; } } } int chk(){ for(int i=1; i<=f[n][k]; i++) if(ind[i]!=0) return -1; int re=0; for(int i=0; i<=k; i++) re = re+dp[f[n][i]]>=p?re+dp[f[n][i]]-p:re+dp[f[n][i]]; return re; } int main(){ cin>>T; while(T--){ init(); spfa(0); spfa(1); build(); topsort(); printf("%d\n", chk()); } return 0; }

luogu3563 逛公園