暂无连接
公交旅行
【题目描述】
蒜头是一位优秀的旅行家。
人类的发展总离不开一代又一代的探险者先驱。追寻前人的轨迹,今天的蒜头到了一个有趣的城市, 和蒜头居住的城市一样有趣。
在这个城市中有 n 个站台和 m 条公交线路,第 i 条公交线路由 ti 个站台组成,记为 si,1,si,2,…,si,ti 。在 0 时刻,第 i 辆公交车会处在 si,1 站台,之后每个时刻公交都会到达路线中的下一个站台。当公交到达终点站后,它下一个时刻将会回到出发的站台,注意一座站台可能在一条线路中出现多次,但不会相邻。
在 0 时刻,蒜头处在站台 1 。如果在某一时刻蒜头和公交在同一个站台,那么蒜头就可以上这辆公交车,并在任意时刻下车,上下车的过程并不会花费时间。作为一位环保的优秀旅行家,蒜头热爱乘坐公交出行。现在蒜头想要知道,如果他只乘坐公交出行,他分别能最早在何时到达每个站台,或是告诉他这 是不可能的。
注意,蒜头一次只能乘坐一辆车,但在通往某个站台的过程中,蒜头可以乘坐许多辆不同的公交车。
【输入】
输入的第一行是两个整数 n,m,分别表示站台和线路的个数。
接下来的 m 行,每行的第一个数为 ti ,表示线路的长度,随后的 ti 个整数描述一条公交线路。
【输出】
共输出 1 行 n−1 个数,第 i 个数表示到达站台 i+1 的最小时间。如果不能到达,输出 −1。
【输入样例】
8 4
2 5 4
3 6 1 2
4 4 2 1 3
2 7 8
【输出样例】
2 3 4 6 3 -1 -1
【提示】
【数据范围】
对于 100% 的数据,ti≥2。
第一个子任务测试点:1,2,…7;
第二个子任务测试点:8,9,10;
第三个子任务测试点:11,12,13;
第四个子任务测试点:14,15,…,29。
题解
处理环和等车是非常麻烦的,所以我们不如直接建图跑最短路,在跑最短路的时候直接加上等车的时间就好了。
计算等车时间需要记录当前时间,环的大小和当前车站在环里的位置,具体见代码。
代码
#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
struct sd{int to,id,pos;};
int n,m,dis[M],vis[M],len[M];
vector<sd>mmp[M];
void in()
{
int a,p1,p2,st;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
{
scanf("%d%d",&a,&st);
len[i]=a;p1=st;
for(int j=2;j<=a;++j)
scanf("%d",&p2),mmp[p1].push_back((sd){p2,i,j-1}),p1=p2;
mmp[p1].push_back((sd){st,i,0});
}
}
int get(int d,int p,int l)
{return (p-(d%l)+l)%l+d;}
void SPFA()
{
memset(dis,127,sizeof(dis));
queue<int>dui;
dui.push(1),vis[1]=1,dis[1]=0;
int f,t,d;
while(!dui.empty())
{
f=dui.front();
dui.pop(),vis[f]=0;
for(int i=mmp[f].size()-1;i>=0;--i)
{
t=mmp[f][i].to;d=get(dis[f]+1,mmp[f][i].pos,len[mmp[f][i].id]);
if(dis[t]>d)
{
dis[t]=d;
if(vis[t])continue;
dui.push(t),vis[t]=1;
}
}
}
}
void ac()
{
SPFA();
for(int i=2;i<=n;++i)
if(dis[i]>1e9)printf("-1 ");
else printf("%d ",dis[i]);
}
int main()
{
in();ac();
return 0;
}