【NOIP 模拟题】旅行(最短路)
【题解】【最短路】
【这道题,明显就是最短路嘛,但是要处理等待时间】
【首先,将每条边拆成两条有向边来存储,用0、1来表示正向边和反向边,每条边还需记录边权(即通过所需的时间)和路径序号】
【t[i][j][0/1]表示从第i个点出发,走第j条路径到起点/终点所需的时间(不包括等待时间)】
【在跑最短路时,还需计算走每一步时的等待时间,设从起点到当前点所需时间为t1,某一路径的列车从起点跑到当前点所需的时间为t2,某趟列车的发车频率为tt,所以等待时间的计算方法为:tt-(((t1-t2)%60+60)%60)%tt。还需特判等待时间为0的情况,这种情况下,计算出来的会是tt。】
【更新答案时,用等待时间加上通过路径所需的时间】
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[20010],nxt[20010],p[2010],val[20010],num[20010],type[20010],tot;
int dis[2010],t[1010][2010][2];
int stop[1010],time[2010],tim[1010];
int n,k,h,s,xx,yy;
bool b[1010];
inline void add(int x,int y,int v,int ty,int nm)
{
tot++; a[tot]=y; nxt[tot]=p[x]; p[x]=tot; val[tot]=v; type[tot]=ty; num[tot]=nm;
}
inline void spfa()
{
queue<int>que;
memset(dis,127/3,sizeof(dis));
memset(b,0,sizeof(b));
dis[xx]=s; que.push(xx); b[xx]=1;
while(!que.empty())
{
int u=que.front(); que.pop();
int v=p[u]; b[u]=0;
while(v!=-1)
{
int t1=dis[u],t2=t[u][num[v]][type[v]];
int tt=time[num[v]];
int ws,we;
ws=tt-(((t1-t2)%60+60)%60)%tt;
if(ws==tt) ws=0;
we=ws+t1;
if(dis[a[v]]>we+val[v])
{
dis[a[v]]=we+val[v];
if(!b[a[v]])
{
b[a[v]]=1;
que.push(a[v]);
}
}
v=nxt[v];
}
}
}
int main()
{
freopen("pod.in","r",stdin);
freopen("pod.out","w",stdout);
int i,j;
memset(p,-1,sizeof(p));
memset(nxt,-1,sizeof(nxt));
scanf("%d%d%d%d%d%d",&n,&k,&xx,&yy,&h,&s);
for(i=1;i<=k;++i)
{
int m;
scanf("%d%d",&m,&time[i]);
for(j=1;j<=m;++j) scanf("%d",&stop[j]);
for(j=1;j<m;++j) scanf("%d",&tim[j]);
for(j=1;j<m;++j)
{
add(stop[j],stop[j+1],tim[j],0,i);
add(stop[j+1],stop[j],tim[j],1,i);
}
for(j=2;j<=m;++j)
t[stop[j]][i][0]=t[stop[j-1]][i][0]+tim[j-1];
for(j=m-1;j>0;--j)
t[stop[j]][i][1]=t[stop[j+1]][i][1]+tim[j];
}
spfa();
dis[yy]-=s;
s+=dis[yy];
h+=(s/60);
s%=60; h%=24;
printf("%d %d\n",h,s);
return 0;
}
既然无能更改,又何必枉自寻烦忧