LGP3953题解
(口胡)
去年刚学 A_star 的时候以为是板子,上午推了一会儿之后受教了
遇到最短路的题先建最短路 DAG,虽然有0边但是先跑一个 Dijkstra。
然后设 \(d[u]\) 是从 \(1\) 到 \(u\) 的最短路径长度, \(f[u][k]\) 是到节点 \(u\) 且路径长度为 \(d[u]+k\) 的路径条数。
那么似乎可以通过每一条边来转移这个类似背包的东西。
那么如果有一个环的长度不大于 \(k\) 呢?
我们不跑背包,将转移树(或者说转移 DAG)来数路径条数,也就是从 \((1,0)\) 到 \((n,0),(n,1)...(n,k)\) 的路径条数。
节点数量是 \(n \times k\) 的,可以通过,如果出现了无穷种方案那么一定出现了一个环,用拓扑排序判断即可。
感觉紫色严重恶评啊(
#include<cstdio>
#include<cctype>
typedef unsigned ui;
const ui M=1e5+5;
ui T,n,m,k,G,P,cnt,h[M],d[M],D[M],t[M<<2],id[M][51];ui u[M<<1],v[M<<1],w[M<<1];
struct Edge{
ui v,nx,w;
}e[M<<2];
inline ui Add(const ui&a,const ui&b){
return a+b>=P?a+b-P:a+b;
}
inline void Add(const ui&u,const ui&v,const ui&w){
e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;
}
inline void Mdf(ui u,const ui&V){
if(~V)d[u]=V;for(D[u]=V,u=u+G>>1;u;u>>=1)t[u]=t[u<<1|(D[t[u<<1]]>D[t[u<<1|1]])];
}
inline void Dijkstra(){
ui u,v,E;for(u=2;u<=n;++u)D[u]=0x7fffffff;D[1]=0;for(G=1;G<=n+1;G<<=1);
for(u=1;u<=n;++u)t[u+G]=u;for(u=G-1;u>=1;--u)t[u]=t[u<<1|(D[t[u<<1]]>D[t[u<<1|1]])];
while(u=t[1])for(Mdf(u,-1),E=h[u];E;E=e[E].nx)if(d[u]+e[E].w-D[v=e[E].v]>>31)Mdf(v,d[u]+e[E].w);
for(u=1;u<=G+n;++u)t[u]=0;
}
struct Graph{
ui cnt,f[M*51],h[M*51],hd[M*51];bool t[M*51],vis[M*51],tag[M*51];ui L,R,q[M*51];
struct Edge{
ui v,nx;
}e[M*102],E[M*102];
inline void Add(const ui&u,const ui&v){
++cnt;e[cnt]=(Edge){v,h[u]};E[cnt]=(Edge){u,hd[v]};hd[v]=h[u]=cnt;
}
inline void init(){
ui e,u;q[L=R=1]=id[n][k];
while(L<=R)for(e=hd[u=q[L++]];e;e=E[e].nx)!t[e[E].v]&&(q[++R]=e[E].v),t[e[E].v]=true;
}
ui DFS(const ui&u){
ui E,x;if(vis[u])return-1;if(tag[u])return f[u];tag[u]=true;vis[u]=true;
for(E=h[u];E;E=e[E].nx,f[u]=::Add(f[u],x))if(!~(x=DFS(e[E].v)))return-1;return vis[u]=false,f[u];
}
}g;
inline ui read(){
ui n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
signed main(){
ui i,j;T=read();D[0]=-1;
while(T--){
n=read();m=read();k=read();P=read();for(i=1;i<=n;++i)for(j=0;j<=k;++j)id[i][j]=++cnt;cnt=0;
for(i=1;i<=k;++i)g.Add(id[n][i-1],id[n][k]);g.f[id[n][k]]=1;
for(i=1;i<=m;++i)u[i]=read(),v[i]=read(),w[i]=read(),Add(u[i],v[i],w[i]);Dijkstra();
for(i=1;i<=m;++i)for(j=0;j+d[u[i]]+w[i]-d[v[i]]<=k;++j)g.Add(id[u[i]][j],id[v[i]][j+d[u[i]]+w[i]-d[v[i]]]);
g.init();for(i=1;i<=id[n][k];++i)if(!g.t[i])g.tag[i]=true;j=g.DFS(1);printf(!~j?"-1\n":"%u\n",j);
for(cnt=g.cnt=0,i=1;i<=n;++i)for(h[i]=D[i]=j=0;j<=k+1;++j){
g.f[id[i][j]]=g.h[id[i][j]]=g.hd[id[i][j]]=g.t[id[i][j]]=g.vis[id[i][j]]=g.tag[id[i][j]]=0;id[i][j]=0;
}
}
}