sgu103

</pre><div>题目大意</div><div>给出一个N个结点的无向图,每条边都有一个长度,但是每条边的两端有信号灯。信号灯有两种颜色:蓝色和紫色,并且信号灯有颜色变化的周期。当要走这条路,这条路的两端</div><div>颜色一样时,才可以走,否则需要等到其中一个等变色后再走(<span style="color: rgb(255, 0, 0);">走这条路的中途不用管灯的颜色</span>)。给定两个点st,ed,求从st到ed最少的时间是多少。</div><div></div><div>我们要注意如果正好在变灯的时间点要按照变了灯算。。。还是最短路,在某个点的时候走过去的花费是在边权(灯一样)or边权+等待(灯不一样等到一样)</div><div>要注意处理一种情况就是两边的灯互相变换,周期相等,这种情况这条路是走不了的</div><div></div><div>不管怎样还是个最短路,spfa也好 dijk也好。。。哪个顺手写那个吧。。。就酱紫。。。</div><div></div><div><pre name="code" class="cpp">#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;

const int maxn = 501;
const int maxm = 15000;
const int inf = 99999999;

int s , t;
int n , m;
int C[maxn] , riC[maxn] , tiB[maxn] , tiP[maxn] ;
int pre[maxm] , other[maxm] , last[maxn] , len[maxm];
int visit[maxn];
int l = 0;

int dist[maxn] , lastx[maxn] , que[maxm*10] , ans[maxn];

int add_edge(int x,int y, int z)
{
	pre[++l] = last[x] ; last[x] = l ; other[l] = y ; len[l] = z ;
	pre[++l] = last[y] ; last[y] = l ; other[l] = x ; len[l] = z ;
}

int prepare()
{
	scanf("%d%d", &s , &t);getchar();
	scanf("%d%d", &n , &m);getchar();
	for (int i = 1 ; i <= n ; i ++)
	{
		char color;
		scanf("%c%d%d%d",&color,&riC[i],&tiB[i],&tiP[i]);
		getchar();
		if (color == 'B') C[i] = 0;
		else C[i] = 1;
	}
	//cout <<"!"<<endl;
	for (int i = 1 ; i <= m ; i ++)
	{
		int p , q, r ;
		scanf("%d%d%d",&p,&q,&r);
		add_edge(p,q,r);
	}
}

void color ( int nowx , int nowtime , int &ca ,int &ta )
{
	if ( nowtime < riC[nowx] ) 
	{
		ta = riC[nowx] ; 
		ca = C[nowx];
		return ;
	}
	else 
	{
		int temp = ( nowtime - riC[nowx] ) % ( tiB[nowx] + tiP[nowx] );
		int now = nowtime - temp ;
		if ( C[nowx] == 1 ) 
		{
			if ( temp < tiB[nowx]) 
			{
				ca = 0 ; 
				ta = now + tiB[nowx];
				return ;
			}
			else 
			{
				ca = 1 ; 
				ta = now + tiB[nowx] + tiP[nowx] ;
				return ;
			}
		}
		else
		{
			if ( temp < tiP[nowx] )
			{
				ca = 1 ;
				ta = now + tiP[nowx];
				return ;
			}
			else 
			{
				ca = 0 ;
				ta = now + tiB[nowx] + tiP[nowx] ; 
				return ;
			}
		}
	}
	
}


int deal(int nowx ,int nowp , int nowtime ,int f)
{
	int ca , cb , ta , tb ;
	int nowy = other[nowp];
	color ( nowx , nowtime , ca , ta );
	color ( nowy , nowtime , cb , tb );
	if (ca == cb ) return nowtime ; 
	if (ta == tb )
	{
		if ( f == 0 ) 
		return deal(nowx , nowp , ta , 1) ;
		else if (nowtime <= riC[nowx] || nowtime <= riC[nowy]) 
		return deal(nowx , nowp , ta , 1);
		else return inf ;
	}
	return min(ta , tb);
}

void spfa()
{
	int l = 0 , r = 1;
	memset( visit , 0 , sizeof( visit ));
	for ( int i = 0 ; i <= t ; i ++ ) dist[i] = inf ;
	que[1] = s ; visit[s] = 1; dist[s] = 0;lastx[s] = 0;

	while ( l != r )
	{
		int x = que[++l];
		for (int p = last[x] ; p != 0; p = pre[p])
		{
			int now = deal( x, p , dist[x] ,0);
			if ( now >= inf ) break;
			if ( len[p] + now < dist[other[p]] ) 
			{
				dist[other[p]] = len[p] + now;
				lastx[other[p]] = x ;
				if ( !visit[other[p]] )
				{
					visit[other[p]] = 1 ;
					que[++r] = other[p] ;
				}
			}
		}
		visit[x] = 0 ;
	}
	if ( dist[t] >= inf ) 
	{
		cout << "0" << endl;
		return ;
	}
	cout << dist[t] <<endl;
	int fw = t , leng = 0 ;
	while ( fw ) 
	{
		ans[++leng] = fw ; 
		fw = lastx[fw];
	}
	for (int i = leng ; i > 1 ; i --)
	{
		printf("%d ", ans[i]);
	}
	printf("%d\n",ans[1]);
	return ;
}

int main()
{
	prepare();
	spfa();
	
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值