版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugar_free_mint/article/details/89066627
题目
找出一条最短路径,使答案为 的倍数
分析
那么要用 表示走到第 个点时最短路径 mod 为w的最短路径,那么其实只需要一个dijkstra+堆优化即可,但是毒瘤出题人卡STL,于是手写堆,但是我太菜了,总是T掉一个点,所以只能开O2了。
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define rr register
using namespace std;
typedef long long ll;
struct node{int y; ll w; int next;}e[200011];
pair<ll,int>heap[2500001]; ll dis[50001][51]; bool v[51][50001];
int cnt,pre[50001][51],pis[50001][51],k=1,ls[50001],n,m,p,s,t;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void Push(pair<ll,int>d){
heap[++cnt]=d;
rr int x=cnt;
while (x>1){
if (heap[x>>1]>heap[x])
swap(heap[x>>1],heap[x]),x>>=1;
else return;
}
}
inline void Pop(){
heap[1]=heap[cnt--];
rr int x=1;
while ((x<<1)<=cnt){
rr int y=x<<1;
if (y<cnt&&heap[y+1]<heap[y]) ++y;
if (heap[y]<heap[x]) swap(heap[y],heap[x]),x=y;
else return;
}
}
inline void print(int x,int y){
if (!pre[x][y]) return;
print(pre[x][y],pis[x][y]);
printf("%d->",pre[x][y]);
}
signed main(){
n=iut(); m=iut(); p=iut(); s=iut(); t=iut();
for (rr int i=1;i<=m;++i){
rr int x=iut(),y=iut(),w=iut();
e[++k]=(node){y,w,ls[x]}; ls[x]=k;
}
memset(dis,127,sizeof(dis));
dis[s][0]=0; heap[++cnt]=make_pair(0ll,s);
while (cnt){
rr ll now1=heap[1].first; rr int x=heap[1].second; Pop();
if (now1%p==0&&x==t) break;
v[now1%p][x]=1;
for (rr int i=ls[x];i;i=e[i].next){
rr ll now=dis[x][now1%p]+e[i].w;
if (now<dis[e[i].y][now%p]){
pre[e[i].y][now%p]=x;
pis[e[i].y][now%p]=now1%p;
dis[e[i].y][now%p]=now;
if (!v[now%p][e[i].y])
Push(make_pair(now,e[i].y));
}
}
}
if (dis[t][0]==dis[0][0]) return !printf("jjc fails in travelling");
printf("%lld\n",dis[t][0]);
print(t,0); return !printf("%d",t);
}