URAL 1980 Road to Investor 二分+最短路

Road to Investor

Time limit: 1.0 second
Memory limit: 64 MB
‘How could I forget it? In  T hours we must show the alpha-version of our game to a potential investor! This meeting is crucial for us! If we miss it, we possibly won’t have a chance to complete the development.’
‘Don’t panic! Where do they wait for us?’
‘In their Tmutarakan office. Let’s go right now. I think we’ll be there in time, but we’ll have to exceed the speed limit in a couple of places.’
‘We don’t need problems with the police—we’ll lose precious time. We’ll work out a route to get to the investor in time such that the maximal needed overspeeding along this route is as minimal as possible.’

Input

The first line contains the number  n of crossroads and the number  m of roads between them (2 ≤  n ≤ 10 000;  1 ≤  m ≤ 10 000).  All the roads have two-way traffic. The  i-th of the following  m lines contains integers  a ib is i, and  l i  (1 ≤  a i <  b i ≤  n;  1 ≤  s i ≤ 300; 1 ≤  l i ≤ 1 000), which mean that there is an  l i-kilometer long road with speed limit  s i kilometers per hour between crossroads  a i and  b i. The game developers’ office is at crossroad 1, and the investor’s office is at crossroad  n. It is guaranteed that there is a way from crossroad 1 to crossroad  n. The last line contains the number  T of hours left before the meeting (1 ≤  T ≤ 10 6).

Output

Describe a route by which the developers can get to the investor’s office in time with minimum overspeeding. In the first line output numbers  S and  k, which are the minimum overspeeding in kilometers per hour and the number of roads in the route. In the second line output  k integers separated with a space. The integers are the numbers of roads in the order in which they must be traveled. The roads are numbered from 1 to  m in the order in which they are given in the input. If there are several ways to get to the investor’s office with the overspeeding  S, output any of them. The absolute or relative error of  S should not exceed 10 −6.

Samples

input output
3 3
1 3 50 150
1 2 80 100
2 3 80 100
2
20.000000 2
2 3
2 1
1 2 60 60
1
0.000000 1
1
Problem Author: Denis Dublennykh
Problem Source: Ural Sport Programming Championship 2013
Tags: none   (
hide tags for unsolved problems
)


直接二分要增加的速度,然后跑最短路,符合条件即可
一开始我是把每段需要的时间先算出来,然后跑出最短的一条路记住,然后就在这条路上二分要增加的速度,WA了11次,都是泪啊


#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>

using namespace std;

#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 0x7FFFFFFF
#define LINF 1000000000000000000LL
#define eps 1e-8


const int maxn=100005;

struct node{
    int u,to,next;
    double l,s;
    int id;
}e[maxn*2];

int n,m;
int head[maxn],vis[maxn];
double dis[maxn];
int edge;
queue<int>q;

int pre[maxn];

int num[maxn];

double t;

void inint()
{
    edge=0;
    CLR(pre);
    CLR(num);
    memset(head,-1,sizeof(head));
}

void addedge(int u,int v,int id,int s,int l)
{
    e[edge].u=u;
    e[edge].to=v;
    e[edge].id=id;
    e[edge].l=l;
    e[edge].s=s;
    e[edge].next=head[u];
    head[u]=edge++;
}


void spfa(double x)
{
    CLR(vis);
    int v,i;
    while(!q.empty()) q.pop();
    for(i=2;i<=n;i++)
       dis[i]=INF;
    dis[1]=0;
    vis[1]=1;
    q.push(1);
    while(!q.empty())
    {
        int tmp=q.front();
        q.pop();
        vis[tmp]=false;
        for(i=head[tmp]; ~i ; i=e[i].next)
        {
            v=e[i].to;
            double w=e[i].l/(e[i].s+x);
            if(dis[v]>dis[tmp]+w)
            {
                dis[v]=dis[tmp]+w;
                pre[v]=tmp;
                num[v]=e[i].id;

                if(!vis[v])
                {
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
    }
}


bool check(double x)
{
    spfa(x);
    if(dis[n]<=t)
      return true;
    return false;
}


int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int a,b;
        double s,l,r;
        int id;

        inint();

        REP(i,m)
        {
            scanf("%d%d%lf%lf",&a,&b,&s,&l);
            id=i+1;
            addedge(a,b,id,s,l);
        }

        scanf("%lf",&t);

        double mid;
        l=0,r=1e8;
        while(fabs(l-r)>eps)
        {
            mid=(l+r)/2;
            if(check(mid))
               r=mid;
            else
               l=mid;
        }

        vector<int> oo;
        oo.clear();
        for(int i=n;i!=1;i=pre[i])
            oo.PB(num[i]);

        int ans=oo.size();
        printf("%.6lf %d\n",mid,ans);
        printf("%d",oo[ans-1]);
        for(int i=ans-2;i>=0;i--)
            printf(" %d",oo[i]);
        cout<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值