【SGU】103. Traffic Lights 最短路

来源:互联网 发布:公章软件免费下载 编辑:程序博客网 时间:2024/05/16 05:59

传送门:【SGU】103. Traffic Lights


题目大意:

在一个N个点M条边的城市里,每个点上有一个交通灯,交通灯亮B、P颜色,在离开始r的时间内交通灯会亮c颜色(c为B、P中的一种),然后开始交替亮B、P颜色,B颜色亮b时间,P颜色亮p时间。M条边经过每条边都有个时间,要走一条边必须要满足这个时刻这条边的两个端点颜色相同,当你正在边上走时两端为什么颜色对你无影响。现在你要从给定的起点s走到终点t,问最小的花费以及路径。


题目分析:

首先我们要明白到达一个点的时间一定是越早越好,所以我们就可以跑最短路了。然后,我们重点要求的就是从一个点到另一个点的花费。

如果我们知道时间,那么就可以得到一个点此时的颜色以及转化过去的最小时间花费。

假设我们现在要经过边(u,v)。

设此时的时间为time_now,u现在颜色为cu_now,v现在颜色为cv_now,u变为下一颜色时的时间为cu_next_time,v变为下一颜色时的时间为cv_next_time。

显然:

1.当cu_now  = cv_now时此时u和v的颜色相同,这个时刻我们就可以走这条边。

2.当cu_now != cv_now时,如果cu_next_time != cv_next_time那么我们取其中较小的一个就好。

3.当cu_now != cv_now且cu_next_time == cv_next_time时,如果u的B颜色周期等于v的P颜色周期且u的P颜色周期等于v的B颜色周期,那么返回INF表示这条边的两个端点的颜色永远不会重叠,因此也无法经过这条边。

4.如果3不满足,说明:

(1)要么u的B颜色周期不等于v的P颜色周期。

(2)要么u的P颜色周期不等于v的B颜色周期。

如果(1)满足那么我们用cu_next_time代入一开始给的时间然后重新计算一遍就好(因为下一次的cu_next_time != cv_next_time,直接眺转至2)。

如果(2)满足那么我们将(1)重复进行两遍就好(因为第一次代入cu_next_time = cv_next_time而第二次才不同,眺转至2)。

我们用一个递归程序实现上面的操作,递归层数不超过2所以可以视为常数。

接下来是另一关键性问题:怎么求一个节点u的下一个颜色以及变为下一颜色时的最短时间?

设time_now为当前时间,color_now为此时颜色,color_next_time为变为下一颜色的最短时间。

令color_pre为节点u还未进入循环前的颜色,r为未进入循环前color_pre的持续时间,b为B颜色的持续时间,p为P颜色的持续时间。

那么当time_now小于进入循环前的持续时间时,color_now就等于初始颜色color_pre,而color_next_time就为r。

如果time_now>=r,那么令tmp = ( time_now - r ) % ( b + p )。

下面分类讨论:

1.如果color_pre为B颜色,且此时tmp<p,则当前颜色为B,时间为time_now + p - tmp。

2.如果color_pre为B颜色,且此时tmp<b,则当前颜色为P,时间为time_now + b + p - tmp。

3.如果color_pre为P颜色,且此时tmp<b,则当前颜色为P,时间为time_now + b - tmp。

4.如果color_pre为P颜色,且此时tmp<p,则当前颜色为B,时间为time_now + b + p - tmp。

既然上面的问题都解决了,那么我们就知道经过一条边的花费了,于是接下来便用最短路算法完成。记得记录路径。


代码如下:


#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std ;#pragma comment(linker, "/STACK:16777216")#define rep( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )#define clr( a , x ) memset ( a , x , sizeof a )#define cpy( a , x ) memcpy ( a , x , sizeof a )const int MAXN = 305 ;const int MAXE = 100005 ;const int INF = 0x3f3f3f3f ;struct Traffic {int color_pre , r , b , p ;void input () {char color[2] ;scanf ( "%s%d%d%d" , color , &r , &b , &p ) ;color_pre = color[0] == 'B' ? 0 : 1 ;}} ;struct Edge {int v , c , n ;Edge () {}Edge ( int v , int c , int n ) : v ( v ) , c ( c ) , n ( n ) {}} ;Traffic node[MAXN] ;Edge E[MAXE] ;int H[MAXN] , cntE ;int d[MAXN] ;int vis[MAXN] ;int pre[MAXN] ;int Q[MAXN] , head , tail ;int S[MAXN] , top ;int s , t ;int n , m ;void clear () {cntE = 0 ;clr ( H , -1 ) ;}void addedge ( int u , int v , int c ) {E[cntE] = Edge ( v , c , H[u] ) ;H[u] = cntE ++ ;}void get_color ( int u , int time_now , int& color_now , int& color_next_time ) {if ( time_now < node[u].r ) {//in precolor_now = node[u].color_pre ;color_next_time = node[u].r ;} else {//in loopint tmp = ( time_now - node[u].r ) % ( node[u].b + node[u].p ) ;if ( node[u].color_pre == 0 ) {if ( tmp < node[u].p ) {color_now = 1 ;color_next_time = time_now + node[u].p - tmp ;} else {color_now = 0 ;color_next_time = time_now + node[u].b + node[u].p - tmp ;}} else {if ( tmp < node[u].b ) {color_now = 0 ;color_next_time = time_now + node[u].b - tmp ;} else {color_now = 1 ;color_next_time = time_now + node[u].b + node[u].p - tmp ;}}}}int get_cost ( int u , int v , int time_now ) {int cu_now , cv_now , cu_next_time , cv_next_time ;get_color ( u , time_now , cu_now , cu_next_time ) ;get_color ( v , time_now , cv_now , cv_next_time ) ;if ( cu_now == cv_now ) return time_now ;//1if ( cu_next_time == cv_next_time ) {if ( node[u].b == node[v].p && node[u].p == node[v].b ) return INF ;//3return get_cost ( u , v , cu_next_time ) ;//4}return min ( cu_next_time , cv_next_time ) ;//2}void spfa () {clr ( d , INF ) ;clr ( vis , 0 ) ;head = tail = 0 ;Q[tail ++] = s ;pre[s] = 0 ;d[s] = 0 ;while ( head != tail ) {int u = Q[head ++] ;if ( head == MAXN ) head = 0 ;vis[u] = 0 ;for ( int i = H[u] ; ~i ; i = E[i].n ) {int v = E[i].v ;int cost = E[i].c + get_cost ( u , v , d[u] ) ;if ( d[v] > cost ) {d[v] = cost ;pre[v] = u ;if ( !vis[v] ) {vis[v] = 1 ;Q[tail ++] = v ;if ( tail == MAXN ) tail = 0 ;}}}}if ( d[t] == INF ) printf ( "0\n" ) ;//not exist a pathelse {printf ( "%d\n" , d[t] ) ;top = 0 ;int x = t ;while ( x ) {S[top ++] = x ;x = pre[x] ;}rev ( i , top - 1 , 0 ) printf ( "%d%c" , S[i] , i ? ' ' : '\n' ) ;}}void solve () {clear () ;int u , v , c ;scanf ( "%d%d" , &n , &m ) ;For ( i , 1 , n ) node[i].input () ;rep ( i , 0 , m ) {scanf ( "%d%d%d" , &u , &v , &c ) ;addedge ( u , v , c ) ;addedge ( v , u , c ) ;}spfa () ;}int main () {while ( ~scanf ( "%d%d" , &s , &t ) ) solve () ;return 0 ;}


0 0
原创粉丝点击