【NOIP 模拟题】旅行(最短路)

                      【NOIP 模拟题】旅行(最短路)_第1张图片

                      【NOIP 模拟题】旅行(最短路)_第2张图片

【题解】【最短路】

【这道题,明显就是最短路嘛,但是要处理等待时间】

【首先,将每条边拆成两条有向边来存储,用0、1来表示正向边和反向边,每条边还需记录边权(即通过所需的时间)和路径序号】

【t[i][j][0/1]表示从第i个点出发,走第j条路径到起点/终点所需的时间(不包括等待时间)】

【在跑最短路时,还需计算走每一步时的等待时间,设从起点到当前点所需时间为t1,某一路径的列车从起点跑到当前点所需的时间为t2,某趟列车的发车频率为tt,所以等待时间的计算方法为:tt-(((t1-t2)%60+60)%60)%tt。还需特判等待时间为0的情况,这种情况下,计算出来的会是tt。】

【更新答案时,用等待时间加上通过路径所需的时间】

#include
#include
#include
#include
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()
{
	queueque;
	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;j0;--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;
}




你可能感兴趣的:(noip,图,最短路,校内互测)