UVA 12661 - Funny Car Racing(最短路)
题目链接 https://cn.vjudge.net/problem/UVA-12661
【题意】
给一个n个结点m条边的有向图(n<=300,m<=50000),每条边是周期性开放和关闭的,每条边用五个整数u,v,a,b,t(1<=u,v<=n,1<=a,b,t<=1e5)表示起点是u,终点是v,通过时间为t秒.这条路会先打开a秒,然后关闭b秒这样子循环下去. 刚开始的时候,每条道路刚刚打开,你必须在道路打开的时候才能进入该道路,并在关闭之前出来,现在你要从源点s出发到达终点t,问你最短时间是多少,保证有解,有重边存在
【思路】
仍然是最短路径,不过要对松弛操作做一定的修改,如果到达点u的最短时间已知,那么在推算接下来其它点的最短时间时,如果这条边仍然开放同时开放的时间够走完这条边,那么就和普通的最短路没有区别. 如果发现不够走完或者这条边是关闭的就需要加上一个等待时间. 另外如果这条边的开放时间小于通过时间那么就直接放弃走这条边
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 330;
struct Edge {
int from,to,a,b,t;
Edge(int f,int t,int aa,int bb,int tt):from(f),to(t),a(aa),b(bb),t(tt) {}
};
struct HeapNode {
int d,u;
HeapNode(int dd,int uu):d(dd),u(uu) {}
bool operator<(const HeapNode& rhs)const {
return d>rhs.d;
}
};
struct Dijkstra {
int n,m;
vector<Edge> edges;
vector<int> g[maxn];
bool done[maxn];
int d[maxn];
void init(int n) {
this->n=n;
for (int i=0; i<n; ++i)
g[i].clear();
edges.clear();
}
void add(int from,int to,int a,int b,int t) {
edges.push_back(Edge(from,to,a,b,t));
m=edges.size();
g[from].push_back(m-1);
}
void dijkstra(int s) {
priority_queue<HeapNode> que;
for(int i=0; i<n; ++i)
d[i]=inf;
d[s]=0;
memset(done,0,sizeof(done));
que.push(HeapNode(0,s));
while(!que.empty()) {
HeapNode x=que.top();
que.pop();
int u=x.u;
if(done[u])
continue;
done[u]=true;
for(int i=0; i<g[u].size(); ++i) {
Edge& e=edges[g[u][i]];
int a=e.a;
int b=e.b;
int t=e.t;
if(a<t)
continue;
if(d[u]%(a+b)+t<=a) {
if(d[e.to]>d[u]+t) {
d[e.to]=d[u]+t;
que.push(HeapNode(d[e.to],e.to));
}
}
else {
int wait=(a+b)-d[u]%(a+b);
if(d[e.to]>d[u]+wait+t) {
d[e.to]=d[u]+wait+t;
que.push(HeapNode(d[e.to],e.to));
}
}
}
}
}
} solver;
int main() {
int n,m,s,e,kase=0;
while(scanf("%d%d%d%d",&n,&m,&s,&e)==4) {
solver.init(n);
for(int i=0; i<m; ++i) {
int u,v,a,b,t;
scanf("%d%d%d%d%d",&u,&v,&a,&b,&t);
solver.add(u-1,v-1,a,b,t);
}
solver.dijkstra(s-1);
printf("Case %d: %d\n",++kase,solver.d[e-1]);
}
return 0;
}