• Spfa【P1813】拯救小tim_NOI导刊2011提高(02)


    Description

    小tim在游乐场,有一天终于逃了出来!但是不小心又被游乐场的工作人员发现了„„所以你的任务是安全地把小tim护送回家。但是,A市复杂的交通状况给你出了一大难题。

    A市一共有n个路口,m条单行马路。但是,每条马路都只有一段时间是开放的。为了安全,你必须选择一条护送路线,使得小tim在路上的时间最短,即到家的时刻减去离开游乐场的时刻最短。

    Input

    第一行4个数,分别是n,m,s,t(2≤n≤100;0≤m≤l000;1≤s,t≤n;s≠t)。基地在路口s,码头在路口t。

    接下来m行每行5个数x,y,b,e,c表示一条x路口到y路口的单行线,在b时刻到e时刻之间开放,需要c的时间通过这条路(必须保证行进在路中间时,路一直开放,否则小tim会被捉住)。两个路口之间可能会有多条道路。一开始的时刻是0(当然,你可以不用马上出发,在基地多呆一段时间)。

    如果不存在任何一种方案使得小tim能成功到达码头,输出“Impossible”。

    Output

    一行,为小tim在路上停留的最短时间。

    首先,我们需要从(s)出去,则必须要考虑从(s)连出的边最早的开放时间.不能考虑其他边的开放时间.

    因此,开始时间要考虑从(s)连出的边.

    (考虑所有边的最早开放时间是会(Wa)掉的 qwq)

    我们设(dis[i])代表到达(i)点的最早时间.

    考虑到达一个新的地方,我们可能停留,又可能迟到其上一个地方.因此对于某一条道路的开放时间和到达上一个地方的时间我们要取(max)

    (dis[v]=max(dis[u],edge[i].a)+edge[i].w)

    注意到这个的话,从(s)开始跑最短路即可.

    由于时间未知,因此我们枚举从(s)出发的时间来得到到达(t)的最短时间。

    注意,要判断能否到达(t)点.

    代码

    #include<cstdio>
    #include<queue>
    #include<iostream>
    #include<cctype>
    #define N 1008
    #define R register
    using namespace std;
    inline void in(int &x)
    {
    	int f=1;x=0;char s=getchar();
    	while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    	while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    	x*=f;
    }
    int n,m,s,t,head[N],tot,dis[N];
    int begin=2147483644,end=-2147483644,ans=2147483647;
    struct cod{int u,v,w,a,b;}edge[N<<1];
    bool vis[N];
    inline void add(int x,int y,int z,int a,int b)
    {
    	edge[++tot].u=head[x];
    	edge[tot].v=y;
    	edge[tot].w=z;
    	edge[tot].a=a;
    	edge[tot].b=b;
    	head[x]=tot;
    }
    inline void spfa(int tm)
    {
    	for(R int i=1;i<=n;i++)dis[i]=2147483647,vis[i]=false;
    	queue<int>q;q.push(s);vis[s]=true;dis[s]=tm;
    	while(!q.empty())
    	{
    		int u=q.front();q.pop();vis[u]=false;
    		for(R int i=head[u];i;i=edge[i].u)
    		{
    			if(max(dis[u],edge[i].a)+edge[i].w<=edge[i].b)
    			{
    				if(max(dis[u],edge[i].a)+edge[i].w<dis[edge[i].v])
    				{
    					dis[edge[i].v]=max(dis[u],edge[i].a)+edge[i].w;
    					if(!vis[edge[i].v])
    					{
    						vis[edge[i].v]=true;
    						q.push(edge[i].v);
    					}
    				}
    			}
    		}
    	}
    }
    int main()
    {
    	in(n),in(m),in(s),in(t);
    	for(R int i=1,x,y,b,e,c;i<=m;i++)
    	{
    		in(x),in(y),in(b),in(e),in(c);
    		if(x==s)begin=min(begin,b);end=max(end,e);
    		add(x,y,c,b,e);
    	}
    	for(R int i=begin;i<=end;i++)
    	{
    		spfa(i);
    		if(dis[t]==2147483647)continue;
    		ans=min(ans,dis[t]-i);
    	}
    	if(ans==2147483647)puts("Impossible");
    	else printf("%d",ans);
    }
    
  • 相关阅读:
    Visio使用遇到的问题
    UML类图符号 各种关系说明以及举例
    测试人员与开发人员之间的关系如何?
    linux命令学习-复制(cp,scp)
    linux服务器报Too many open files的解决方法
    QTP学习一添加默认的注释及调用外部vbs文件
    关于JAVA应用中文字体显示小方框的问题解决
    web测试方法总结
    linux命令学习-su
    Oracle定义varchar2()类型存储汉字的长度问题
  • 原文地址:https://www.cnblogs.com/-guz/p/9799761.html
Copyright © 2020-2023  润新知