UVA 12661 Funny Car Racing 有趣的赛车比赛(最短路,变形)

时间:2023-03-08 16:45:41

题意:赛道有n个交叉点,和m条单向路径(有重边),每条路都是周期性关闭的,且通过仍需一段时间。在比赛开始时,所有道路刚好打开,选择进入该道路必须满足“在打开的时间段进入,在关闭之前出来”,即不可在路上逗留,但是可以在交叉点逗留。问到达终点的时间要多少?

思路:最短路,而且正权,用Dijkstra+优先队列够了。主要的难点在计算是否可以进入该路段,画图清晰点。

 #include <bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define INF 0x7f7f7f7f
using namespace std;
const int N=+;
vector<int> vect[]; struct node
{
int from;
int to;
int a;
int b;
int len; }edge[N];
int edge_cnt; void add_node(int u,int v,int a,int b,int t)
{
edge[edge_cnt].from=u;
edge[edge_cnt].to=v;
edge[edge_cnt].a=a;
edge[edge_cnt].b=b;
edge[edge_cnt].len=t;
vect[u].push_back(edge_cnt++);
} int dis[];
bool vis[]; int Dijkstra(int s,int e)
{
memset(vis,,sizeof(vis));
memset(dis,0x7f,sizeof(dis));
priority_queue<pii, vector<pii>, greater<pii> > que;
que.push(make_pair(,s));
dis[s]=; while(!que.empty()) //每次用一个点来更新别人
{
int x=que.top().second; que.pop();
if(vis[x]) continue; //遍历过
vis[x]=;
for(int i=; i<vect[x].size(); i++)
{
node e=edge[vect[x][i]];
if( dis[x]%(e.a+e.b)+e.len<=e.a
&& dis[e.to]>dis[x]+e.len ) //在可通过时间段
{
dis[e.to]=dis[x]+e.len;
que.push(make_pair(dis[e.to],e.to));
}
else if( dis[e.to]>dis[x]+e.len+ (e.a+e.b-dis[x]%(e.a+e.b)) ) //要等待
{
dis[e.to]=dis[x]+e.len+ (e.a+e.b-dis[x]%(e.a+e.b)) ;
que.push(make_pair(dis[e.to],e.to));
}
}
}
return dis[e];
} int main()
{ freopen("input.txt", "r", stdin); int n, m, s, t, u, v, a, b, tt, j=;
while(~scanf("%d%d%d%d",&n,&m,&s,&t))
{
for(int i=; i<=n; i++) vect[i].clear();
memset(edge,,sizeof(edge));
edge_cnt=; for(int i=; i<m; i++)
{
scanf("%d %d %d %d %d", &u, &v, &a, &b, &tt );
if(a>=tt) add_node(u, v, a, b, tt);//去掉废路
}
printf("Case %d: %d\n", ++j, Dijkstra(s,t));
}
return ;
}

AC代码