题意:在一场在比赛中,有n个结点,有m条连线,每一条边有属性a,b。a代表边的门打开时间,b代表门关闭的时间。周期循环。车字通过每条边需要时间,如果通过的时间小于门打开的时间,则不能通过,等待下一次开门。(如果在一个完整的周期中,通过的时间仍小于门打开的时间,则不能通过这条边).
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=310;
const int INF = (1<<30);
int n,m;
struct edge
{
int from,to,dist,a,b;
edge(int from,int to,int dist,int a,int b):from(from),to(to),
dist(dist),a(a),b(b){}
};
struct node
{
int x,d;
node(int x,int d):x(x),d(d){}
};
struct cmp
{
bool operator() (node a,node b)
{
return a.d>b.d;
}
};
vector<edge> v;
vector<int> g[maxn];
priority_queue<node,vector<node>,cmp > q;
int d[maxn],vis[maxn];
void add(int from,int to,int dist,int a,int b)
{
v.push_back(edge(from,to,dist,a,b));
int m=v.size()-1;
g[from].push_back(m);
}
void dijkstra(int s)//单源最短路径
{
memset(vis,0,sizeof(vis));
for(int i=0;i<=n;i++)
d[i]=INF;
d[s]=0;
while(!q.empty())q.pop();
q.push(node(s,0));
while(!q.empty())
{
node x=q.top();
q.pop();
int u = x.x; //选择d最小的点u,在第一步中一定是起点
if(vis[u])continue;
vis[u]=1;
for(int i=0;i<g[u].size();i++)//访问全部相邻点
{
edge e=v[g[u][i]];
int y=e.to;
int a=e.a;int b=e.b;int t=e.dist;
if(t>a)continue;
int now = d[u]%(a+b);
if(now+t<=a)
{
if(d[y]>d[u]+e.dist)
d[y]=d[u]+e.dist;
q.push(node(y,d[y]));
}
else
{
int wait=a-now+b;
if(d[y]>d[u]+e.dist+wait)
d[y]=d[u]+e.dist+wait;
q.push(node(y,d[y]));
}
}
}
}
int main()
{
int s,t,kcase=0;
while(scanf("%d%d%d%d",&n,&m,&s,&t)!=EOF)
{
int u,v1,a,b,t1;
for(int i=1;i<=n;i++)
g[i].clear();
v.clear();
for(int i=0;i<m;i++)
{
scanf("%d%d%d%d%d",&u,&v1,&a,&b,&t1);
add(u,v1,t1,a,b);
}
dijkstra(s);
printf("Case %d: %d\n",++kcase,d[t]);
}
}