题意:求a点与b点间所有k的倍数长度的路径中最短的一条。
题解:先做一遍拓扑序,再spfa维护dis[i][j],i表示到第i个点,j表示该最短距离%k=j。
代码附上
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
const int INF=0x3f3f3f3f;
int n,m,s,a,b;
int hj[1005][1005],hk[1005][1005],c[1005],d[1005],g[1005];
int f[1005][1005];
int main()
{
scanf("%d%d%d%d%d",&n,&m,&s,&a,&b);
a-=1;
b-=1;
int x,y,z;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
x-=1;
y-=1;
c[x]++;
d[y]++;
hj[x][c[x]]=z;
hk[x][c[x]]=y;
}
g[0]=n;
int t=0;
for(int i=0;i<n;i++)
{
if(d[i]==0)//入度为0,加到集合G;
{
t++;
g[t]=i;
}
}
int j=-1;
while(t<n)
{
j++;
x=g[j];
for(int i=1;i<=c[x];i++)
{
y=hk[x][i];
d[y]--;
if(d[y]==0)
{
t++;
g[t]=y;
}
}
}//拓扑
for(int i=0;i<n;i++)
{
for(int l=0;l<s;l++)
{
f[i][l]=INF;
}
}
for(int i=1;i<=n;i++)
{
if(g[i]==a)//找到起点
{
f[g[i]][0]=0;
j=i;
break;
}
}
j--;
int o;
while(g[j]!=b)
{
j++;
x=g[j];
for(int i=0;i<s;i++)
{
if(f[x][i]<INF)
{
for(int k=1;k<=c[x];k++)
{
y=hk[x][k];
z=hj[x][k];
o=(z+i)%s;
if(f[y][o]>f[x][i]+z)
f[y][o]=f[x][i]+z;
}
}
}
}//spfa
if(f[b][0]<INF)
cout<<f[b][0]<<endl;
else
cout<<endl;
}