sgu103 SPFA水题

sgu103本来是一个水题,但是因为小错误调试了两天。。。

#include<queue>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
const int inf=1000000;
using namespace std;
int dis[310],start,end,last[310];
int bgn[310],to[28010],nxt[28010],w[28010];
struct cross
{
	bool c;
	int rc,t[2];
}a[310];
struct situation
{
	bool c;
	int et;
}s,e,da;
int n,m,cnt;
void add_edge(int x,int y,int z)
{
	cnt++;
	nxt[cnt]=bgn[x];
	bgn[x]=cnt;
	to[cnt]=y;
	w[cnt]=z;
}
situation getans(int i,int time)
{
	if(time<a[i].rc)
	{
		da.et=a[i].rc-1-time;
		da.c=a[i].c;
	}
	else
	{
		time-=a[i].rc;
		time-=(time/(a[i].t[0]+a[i].t[1]))*(a[i].t[0]+a[i].t[1]);
		if(time<a[i].t[!a[i].c])
		{
			da.et=a[i].t[!a[i].c]-1-time;
			da.c=!a[i].c;
		}
		else
		{
			da.et=a[i].t[a[i].c]+a[i].t[!a[i].c]-1-time;
			da.c=a[i].c;
		}
	}
	return da;
}
char s1[10];
void putout(int x)
{
	if(last[x])putout(last[x]);
	printf("%d ",x);
}
void SPFA()
{
	queue<int>q;
	for(int i=1;i<=n;i++)
		dis[i]=inf;
	dis[start]=0;
	q.push(start);
	while(!q.empty())
	{
		int x=q.front();q.pop();
		for(int i=bgn[x];i;i=nxt[i])
		{
			int now=0,p=to[i],sum=0;
			s=getans(x,dis[x]);
			e=getans(p,dis[x]);
			while(sum<=3&&dis[x]+now+w[i]<dis[p])
			{
				if(s.c==e.c)break;
				else 
				{
					if(s.et!=e.et)
					{
						now=min(s.et+1,e.et+1);
						break;
					}
					else
					{
						if(dis[x]==0&&now==0)now+=a[x].rc;
						else now+=a[x].t[s.c];
						s.et+=a[x].t[!s.c];
						e.et+=a[p].t[!e.c];
						s.c=!s.c;
						e.c=!e.c;
					}
				}
				sum++;
			}
			if(dis[x]+now+w[i]<dis[p]&&sum<=3)
			{
				dis[p]=dis[x]+now+w[i];
				last[p]=x;
				q.push(p);
			}
		}
	}
	if(dis[end]==inf)printf("0\n");
	else 
	{
		printf("%d\n",dis[end]);
		putout(end);
	}
	return;
}
int main()
{
	int x,y,z;
	scanf("%d%d",&start,&end);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s1);
		if(s1[0]=='B')a[i].c=1;
		scanf("%d%d%d",&a[i].rc,&a[i].t[1],&a[i].t[0]);
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		add_edge(x,y,z);
		add_edge(y,x,z);
	}
	SPFA();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值