[noip模拟赛]旅行Pod(spfa)

来源:互联网 发布:淘宝店铺pc端装修视频 编辑:程序博客网 时间:2024/06/05 04:38

题目描述

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

题解

一眼看上去就是最短路嘛,只不过有一点变形而已。
将所有的边都拆成正反有向边,对于每一条边<u,v>记录一下信息:边权c,路线k,0/1分别表示路线k正向或反向。
预处理t[i][j][k]表示第i个点,从第j条路线的起点/终点(k=0/1)跑到需要跑多少时间。
然后跑spfa。每一次更新的时候,根据枚举到的边的信息,算出在该点最少还需要等多长时间能搭上通向这条路的车,其余的正常做就行。
跑spfa的时候就是计算时间的时候比较容易出错。假设起点到当前点花的时间为pt1,某一趟列车从它的起点到这个点需要跑pt2的时间,列车的周期为T的话,那么需要等的时间为T(((pt1pt2)%60+60)%60)%T,即要等到pt1+T(((pt1pt2)%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 10005int 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、这道题计算时间的细节非常值得推敲,以后细节要格外注意,想得更清楚一些。

0 0
原创粉丝点击