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;
		}
	}
}
posted @ 2022-01-11 15:00  Prean  阅读(25)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};