传送门:【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 ;
}

【SGU】103. Traffic Lights 最短路相关推荐

  1. SGU 103 Traffic Lights(最短路)

    这题不错,是一个最短路,但是中间有一个限制条件,就是等待时间 首先先看一下为什么仍然满足最短路 因为最短路肯定是每个结点求出最早到达的时间,那么其实不管有没等待,从队头取出去转移的肯定是最早的时间,仍 ...

  2. [SGU 103] Traffic Lights [最短路]

    现在给你一个城市网络,求从某点到某点的最短路.每个点上都有一个红绿灯,仅有红绿两种颜色,按照某个周期切换,尽在边的两个端点的灯同色时,这条边才可走. 直接用最短路算法即可,走某条路径之前要加上的等待灯 ...

  3. SGU 103 Traffic Lights (最短路)

    题意:http://www.cnblogs.com/yylogo/archive/2011/06/05/SGU-103.html 分析:比通常的最短路问题多了个限制条件,即每个路口的颜色必须相同时才能 ...

  4. SGU 103 Traffic Lights【最短路】

    题目链接: http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=16530 题意: 给定每个点最初的颜色,最初颜色持续时间,以 ...

  5. SGU 103 Traffic Lights

    http://acm.sgu.ru/problem.php?contest=0&problem=103 有条件限制的最短路问题,当且仅当点的颜色一样时可以通行否则需要等到符合条件时才可以通行. ...

  6. SGU 103 Traffic Lights 翻译 题解

    103. 交通灯 每个测试点:0.5s 内存限制:4096KB 在Dingilville市城市交通的安排很不寻常,公路连接着路口,在两个不同的路口之间最多有一条公路连接,没有公路会连接一个路口自身.正 ...

  7. CodeForces刷题C语言:Next Test、Spit Problem、Traffic Lights、Reconnaissance、Borze

    记录洛谷刷题C语言 一.Next Test 题面翻译 题面描述 给出 nnn 个互不相同的整数 aia_iai​ ,从小到大找第一个没有出现过的整数. 输入格式 第一行一个正整数 nnn ,之后是 n ...

  8. Traffic Lights(翻译)

    来源:https://codeforces.com/contest/29/problem/B Traffic Lights A car moves from point A to point B at ...

  9. signature=23e9377f593aff2d118917dcf0d9f6d0,Turning streams in the traffic lights system

    摘要: Observations of a currently functioning in Poland traffic lights system shows a need for it's mo ...

最新文章

  1. 仅用语音,AI就能“脑补”你的脸! | 技术头条
  2. win10无线投屏_日臻薄技 | 手机如何投屏到电脑
  3. socket服务器显示未响应,“程序未响应”的思考总结
  4. 图像处理傅里叶变换的理解及其matlab实现
  5. android 状态栏、标题栏、屏幕高度
  6. SEO | 重新认识一下Meta标签
  7. linux 内核配置 dns,linux bind dns简单配置
  8. Django通过中间件实现登录验证demo
  9. vue2.0 路由不显示router-view
  10. 盘一盘 Thread源码
  11. windows server 2008 安装linux,使用WSL在Windows Server 2019上运行Linux的方法
  12. pdf电脑地址转网络地址.txt
  13. 公用Laravel 5框架与公用库架构
  14. flash cs6 快捷键
  15. SQL Server如何备份数据库?完整数据库备份方式
  16. 终极指南 | 干了这篇收心文,从入门到精通手把手教你写出最牛白皮书!
  17. python字符串输入并倒叙_基于python3实现倒叙字符串
  18. 网易5天python编程课_网易云课堂上自学编程?
  19. RTX3090 GPU环境配置
  20. 第二十二章 : 格式化输出

热门文章

  1. 用html标签编写古诗,怎么用html/css写一首古诗
  2. 20计算机考研,很多大学被【撤销专业】!
  3. html5鱼游动动画,CSS和D3制作小鱼游动的交互动画效果
  4. 地图建筑群的光影效果原理和应用实践
  5. python爬虫爬取豆瓣图书热评并生成图云
  6. 【转】VB编程的八个优良习惯
  7. 中央空调如何调节温度html,中央空调温度怎么设定 中央空调温度调节方法【详解】...
  8. 中软实习培训记录三(0722)
  9. 史上最全的计算机网络知识点总结
  10. ner 评估指标_2019-03 NER命令实体识别归纳