题意:
求一个有向图中s到t的最短路,特别的是每条路除了花费时间还有开放时间区间,只有在开放时间区间内才能使用这条路。
分析:
直接用spfa求最短路即可,需要注意的是因为最后所求最短时间是从离开s开始算,所以要枚举离开s的时间。
代码:
//poj 3594
//sepNINE
#include <iostream>
#include <queue>
using namespace std;
const int maxN=128;
const int maxM=1024;
int n,e,s,d,m;
int head[maxN],arrive[maxN],inq[maxN];
queue<int> Q;
struct Edge{
int v,st,et,t,next;
}edge[maxM];
void addEdge(int x,int y,int st,int et,int t)
{
edge[e].v=y;edge[e].st=st;edge[e].et=et;edge[e].t=t;
edge[e].next=head[x];head[x]=e++;
}
int spfa(int time)
{
int i,j,k,ans=INT_MAX;
for(i=1;i<=n;++i)
arrive[i]=INT_MAX;
while(!Q.empty()) Q.pop();
memset(inq,0,sizeof(inq));
arrive[s]=time;
Q.push(s);
inq[s]=1;
while(!Q.empty()){
int u=Q.front();
Q.pop();
inq[u]=0;
for(i=head[u];i!=-1;i=edge[i].next){//贪心,每个点都争取最小的到达时间,若对u有两个arrive值arr1,arr2且arr1<arr2,则arr1的更新空间肯定大于包含arr2的更新空间,故在每个点贪心地选择较小的arrive值。
int v=edge[i].v,st=edge[i].st,et=edge[i].et,t=edge[i].t;
if(arrive[u]>=st){
if(arrive[u]+t<=et&&arrive[u]+t<arrive[v]){
arrive[v]=arrive[u]+t;
if(inq[v]==0){
inq[v]=1;
Q.push(v);
}
}
}
else{//arrive[u]<st 要等到st才能走
if(st+t<=et&&st+t<arrive[v]){
arrive[v]=st+t;
if(inq[v]==0){
inq[v]=1;
Q.push(v);
}
}
}
}
}
if(arrive[d]==INT_MAX)
return INT_MAX;
else
return arrive[d]-time;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&d);
e=0;
memset(head,-1,sizeof(head));
int mint=INT_MAX,maxt=-1;
while(m--){
int x,y,st,et,t;
scanf("%d%d%d%d%d",&x,&y,&st,&et,&t);
if(t<=et-st){
addEdge(x,y,st,et,t);
if(x==s){
mint=min(mint,st);
maxt=max(maxt,st);
}
}
}
int ans=INT_MAX;
for(int i=mint;i<=maxt;++i){
int tmp=spfa(i);
if(tmp==INT_MAX)
break;
ans=min(ans,tmp);
}
if(ans==INT_MAX)
printf("Impossible\n");
else
printf("%d\n",ans);
return 0;
}
本文介绍了一种特殊的最短路径问题解决方案,该问题考虑了边的时间窗口限制。通过SPFA算法实现,允许边仅在特定时间段内可用,并讨论了如何枚举出发时间以找到从起点到终点的最短路径。

119

被折叠的 条评论
为什么被折叠?



