题目描述
题解
一眼看上去就是最短路嘛,只不过有一点变形而已。
将所有的边都拆成正反有向边,对于每一条边<u,v>记录一下信息:边权c,路线k,0/1分别表示路线k正向或反向。
预处理t[i][j][k]表示第i个点,从第j条路线的起点/终点(k=0/1)跑到需要跑多少时间。
然后跑spfa。每一次更新的时候,根据枚举到的边的信息,算出在该点最少还需要等多长时间能搭上通向这条路的车,其余的正常做就行。
跑spfa的时候就是计算时间的时候比较容易出错。假设起点到当前点花的时间为pt1,某一趟列车从它的起点到这个点需要跑pt2的时间,列车的周期为T的话,那么需要等的时间为T−(((pt1−pt2)%60+60)%60)%T,即要等到pt1+T−(((pt1−pt2)%60+60)%60)%T这个时间再出发。注意这里的时间是以整点计算的,即在起点处pt1=mx。
还需要注意的一点是,当pt1=pt2时,等待的时间应该为0,但是用上面的式子计算出来应该是T,也就是恰好多了一个周期。这种情况需要特判一下。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define N 1005
#define E 10005
int n,k,x,y,gx,mx,s;
struct ANS{int g,m;}ans;
int C[N*2],st[N*2],p[N],r[N],t[N][N*2][2],dis[N];
int tot,point[N],nxt[E*2],v[E*2],c[E*2],K[E*2],ty[E*2];
bool vis[N];
queue <int> q;
inline void addedge(int x,int y,int z,int k,int i)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z; K[tot]=k; ty[tot]=i;
}
inline void spfa()
{
memset(dis,127/3,sizeof(dis)); dis[x]=mx;
memset(vis,0,sizeof(vis)); vis[x]=true;
while (!q.empty()) q.pop(); q.push(x);
while (!q.empty())
{
int now=q.front(); q.pop();
vis[now]=false;
for (int i=point[now];i;i=nxt[i])
{
int pt1=dis[now];
int pt2=t[now][K[i]][ty[i]];
int T=C[K[i]];
int waiting,waito;
waiting=T-(((pt1-pt2)%60+60)%60)%T;
if (waiting==T) waiting=0;
waito=pt1+waiting;
if (waito+c[i]<dis[v[i]])
{
dis[v[i]]=waito+c[i];
if (!vis[v[i]])
{
vis[v[i]]=true;
q.push(v[i]);
}
}
}
}
}
inline ANS calc(int g,int m,int len)
{
ANS ans;
m+=len;
g+=m/60;
m%=60;
g%=24;
return ans=(ANS){g,m};
}
int main()
{
freopen("pod.in","r",stdin);
freopen("pod.out","w",stdout);
scanf("%d%d%d%d%d%d",&n,&k,&x,&y,&gx,&mx);
for (int i=1;i<=k;++i)
{
scanf("%d%d",&s,&C[i]);
for (int j=1;j<=s;++j) scanf("%d",&p[j]);
for (int j=1;j<s;++j) scanf("%d",&r[j]);
for (int j=1;j<s;++j)
{
addedge(p[j],p[j+1],r[j],i,0);
addedge(p[j+1],p[j],r[j],i,1);
}
for (int j=2;j<=s;++j)
t[p[j]][i][0]=t[p[j-1]][i][0]+r[j-1];
for (int j=s-1;j>=1;--j)
t[p[j]][i][1]=t[p[j+1]][i][1]+r[j];
}
spfa();
ans=calc(gx,mx,dis[y]-mx);
printf("%d %d\n",ans.g,ans.m);
}
总结
1、这道题计算时间的细节非常值得推敲,以后细节要格外注意,想得更清楚一些。