拯救小tim

来源:互联网 发布:我国加工贸易现状知乎 编辑:程序博客网 时间:2024/05/16 06:12

【问题描述】
小tim在游乐场,有一天终于逃了出来!但是不小心又被游乐场的工作人员发现了。。。 所以你的任务是安全地把小tim护送回家。
但是,A市复杂的交通状况给你除了一个难题。
A市一共有n个路口,m条单行马路。但是,每条马路都只有一段时间是开放的。为了 安全,你必须选择一条护送路线,使得小
tim在路上的时间最短,即到家的时刻减去离开游
乐场的时刻最短。
【样例解释】
最优方案应该是,在1号点停留至时刻1,然后走到3号点,然后走到4号点。到达时 刻为时刻4。在路上的时间为4-1=3。

【输入格式】

第一行4个数,分别是n,m,s,t(2<=n<=100;0<=m<=1000;1<=s,t<=n,s≠t)。基地在路口s,码头在路口t。
接下来m行每行5个数x,y,b,e,c 表示一条x路口到y路口的单行线,在b时刻到e时刻之间开放,需要c的时间通过这条路
(必须保证行进在路中间时,路一直开放,否则小tim会被捉住)。两个路口之间可能会有多条道路。一开始的时刻是0(当然
,你可以不用马上出发,在基地多呆一段时间)。
如果不存在任何一种方案使得小tim能成功到达码头,输出“Impossible”。

【输出格式】
一行,为小tim在路上停留的最短时间

Sample Input
4 5 1 4
1 2 0 1 1
1 2 0 1 2
1 3 1 3 2
2 4 3 4 1
3 4 3 4 1
Sample Output
3

解题思路:
一道非常巧妙的SPFA题目。我们可以按照时间点进行SPFA。
1.首先,如果到了当前节点而当前的路还没有开放,那就应该按照开放的时间点向下走,如果开放了而晚到了,那就按晚到的时间,所以应该取max。
2.按照出发的时间点进行spfa,取最早的出发点和最晚的出发点进行SPFA。
3.SPFA时,点能进入队列有两个条件:1.在道路关闭之前到达。2.时间最短。

#include<iostream>#include<cstring>#include<cstdio>#include<queue>using namespace std;queue<int>q;struct node{    int from,to,l,r,ds;}list[1005];int minn,k,maxx=-1e9,n,m,s,t,x,y,l,r,c,ans;int head[1005],dis[1005],v[1005];void add(int x,int y,int l,int r,int c){    list[++k].from=head[x];    list[k].to=y;    list[k].l=l;    list[k].r=r;    list[k].ds=c;    head[x]=k;}void spfa(int x){    memset(dis,127/3,sizeof(dis));    memset(v,0,sizeof(v));    q.push(s);dis[s]=x;v[s]=1;    while(!q.empty()){        int u=q.front();q.pop();v[u]=0;        for (int i=head[u];i;i=list[i].from){        if (max(dis[u],list[i].l)+list[i].ds<=list[i].r)        if (max(dis[u],list[i].l)+list[i].ds<dis[list[i].to]){            dis[list[i].to]=max(dis[u],list[i].l)+list[i].ds;            if (!v[list[i].to]){                v[list[i].to]=1;                q.push(list[i].to);            }        }    }}}int main(){    cin>>n>>m>>s>>t;    ans=minn=1e9;    for (int i=1;i<=m;i++){        scanf("%d%d%d%d%d",&x,&y,&l,&r,&c);        if (l>r) swap(l,r);        if (l+c>r) continue;        if (x==s){            minn=min(minn,l);            maxx=max(maxx,r-c);        }        add(x,y,l,r,c);    }    for (int i=minn;i<=maxx;i++){        spfa(i);        if (dis[t]==dis[0]) break;//优化,如果某一时刻到达不了,那后来的也就到达不了了。        ans=min(ans,dis[t]-dis[s]);    }    if (ans==1e9) cout<<"impossible";    else     cout<<ans;    return 0;}