【题目描述】
在dingilville城中交通由一些道路构成。每个节点由一些道路连接而成。两个不同的节点之间最多拥有一条路,没有一条路连向自己,所需时间与路的长度相同。每一个点都有一个信号灯,在任何时刻它是蓝色或者紫色, 每一种颜色是周期变化的:蓝色持续一段时间然后紫色持续一段时间。允许你沿着一路从一个点到另一个点,此时必须满足着两个点的 信号灯的颜色在这一段时间内相同。今有一张城市地图它包括下列信息:
1.每一条路的长度即所需时间(整数)
2.每个节点信号灯两种颜色持续的时间(整数)
3.每个点信号灯最初的颜色和它持续的时间
你的任务是找到一条路试的从源点到汇点的旅行时间最短。
它包括哪些路你必须需要走的。
【输入格式】
第一行两个整数 源点和汇点的标号
第二行两个整数 总共有n个节点 m条边
下接n行 每行是一个节点的信息,共四个整数
c r tB tP
c表示该节点最初的颜色
r表示最初颜色持续的时间
tB 蓝色持续的时间
tP 紫色持续的时间
下接m行 每行为一条边的信息,共三个整数
i j lij——始边 终边 长度
【输出格式】
若存在路径
第一行包括从源点到汇点的最短路
第二行包含从源到汇的最短路径
若不存在路径
一个整数0
【样例】
input
1 4
4 5
B 2 16 99
P 6 32 13
P 2 87 4
P 38 96 49
1 2 4
1 3 40
2 3 75
2 4 76
3 4 77
【数据范围】
n<=300
m<=14000
lig<100
对于出现的一些逗B错误进行小结
在dingilville城中交通由一些道路构成。每个节点由一些道路连接而成。两个不同的节点之间最多拥有一条路,没有一条路连向自己,所需时间与路的长度相同。每一个点都有一个信号灯,在任何时刻它是蓝色或者紫色, 每一种颜色是周期变化的:蓝色持续一段时间然后紫色持续一段时间。允许你沿着一路从一个点到另一个点,此时必须满足着两个点的 信号灯的颜色在这一段时间内相同。今有一张城市地图它包括下列信息:
1.每一条路的长度即所需时间(整数)
2.每个节点信号灯两种颜色持续的时间(整数)
3.每个点信号灯最初的颜色和它持续的时间
你的任务是找到一条路试的从源点到汇点的旅行时间最短。
它包括哪些路你必须需要走的。
【输入格式】
第一行两个整数 源点和汇点的标号
第二行两个整数 总共有n个节点 m条边
下接n行 每行是一个节点的信息,共四个整数
c r tB tP
c表示该节点最初的颜色
r表示最初颜色持续的时间
tB 蓝色持续的时间
tP 紫色持续的时间
下接m行 每行为一条边的信息,共三个整数
i j lij——始边 终边 长度
【输出格式】
若存在路径
第一行包括从源点到汇点的最短路
第二行包含从源到汇的最短路径
若不存在路径
一个整数0
【样例】
input
1 4
4 5
B 2 16 99
P 6 32 13
P 2 87 4
P 38 96 49
1 2 4
1 3 40
2 3 75
2 4 76
3 4 77
【数据范围】
n<=300
m<=14000
lig<100
r<t
【问题分析】
简而言之,就是一张随着时间变化连通性的地图,求解单源最短路。我们可以考虑SPFA、dijkstra两种常见的单源最短路算法。最重要的是判断两点在某一时刻是否可以走,如果不可以则求得最小等待时间,如果永远不可以走:即这两盏灯在任意时刻灯的颜色都不同,或者可以换而言之,初相位相异,周期不同。不过事实上有如下代码【表示个人代码风格十分奇葩】
int wait(int x,int y)//考虑x y两个点需要等待的时间
{
int now,tmp;//当前时间
int cx,cy,rx,ry,nx,ny;
/*
简述我的逗比时间函数
首先求出当前时间两个灯的颜色
然后运行一个周期找到两个灯颜色相同的时候
*/
/*
c- B 0
P 1
当前x点灯的颜色 cx 此时已经经过该颜色的时间为 rx
下一个变动的时刻 now+p[x].time[cx]-rx 此时的颜色为1-cx
当前y点灯的颜色 cy 此时已经经过该颜色的时间为ry
下一个变动的时刻 now+p[y].time[cx]-ry 此时的颜色为1-cy
呵呵简直就是在虐我的键盘 %>_<%
*/
now=dist[x];
if (now<p[x].r)
{
cx=p[x].c;
rx=now;
nx=p[x].r;
}
else
{
rx=(now-p[x].r)%(p[x].time[2]);
cx=1-p[x].c;
if (rx>=p[x].time[1-p[x].c])
{
rx-=p[x].time[1-p[x].c];
cx=1-cx;
}
nx=now+p[x].time[cx]-rx;
}
if (now<p[y].r)
{
cy=p[y].c;
ry=now;
ny=p[y].r;
}
else
{
ry=(now-p[y].r)%(p[y].time[2]);
cy=1-p[y].c;
if (ry>=p[y].time[1-p[y].c])
{
ry-=p[y].time[1-p[y].c];
cy=1-cy;
}
ny=now+p[y].time[cy]-ry;
}
if (cx==cy)
return now;
if (nx<ny)
return nx;
if (nx==ny)//当前变化时间相同,但是我们只是运行了每个点周期的一半,即我们只是把蓝色变成紫色,或者把紫色变成蓝色的时间相同,可能在另一半不同
{
nx=nx+p[x].time[1-cx];
ny=ny+p[y].time[1-cy];
if (nx==ny) //周期性可知确实是一直不可走的
return -1;
if (nx<ny)
return nx;
else
return ny;
}
if (nx>ny)
return ny;
}
蒽,上面这段代骂确实是整个程序的核心部分,有很多版本的写法,这个只不过是其中一个。
下面是AC代码
<script src="https://code.csdn.net/snippets/505407.js"></script>
对于出现的一些逗B错误进行小结
【各种错误】
WA test5
额,真是没有想到前四个点有多弱,我把无向图存成有向图,时间判断忘记刚好到变灯时刻需要变灯(举例 若 5秒中时变灯,当时间为5秒时,已经变灯)
呵呵,我能说SGU格式错误很逗么。。。
额,SGU的PE真是醉人!!!