1806: Toll
Time Limit: 5 Sec Memory Limit: 128 Mb Submitted: 266 Solved: 82 SpecialJudgeDescription
In ICPCCamp, there are
n cities and
m unidirectional roads between cities. The
i-th road goes from the a
i-th city to the b
i-th city. For each pair of cities
uand
v, there is at most one road from
u to
v.
As traffic in ICPCCamp is becoming heavier, toll of the roads also varies. At time
t, one should pay (c
i⋅t+d
i) dollars to travel along the
i-th road.
Bobo living in the 1-st city would like to go to the n-th city. He wants to know the average money he must spend at least if he starts from city 1 at
t∈[0,T]. Note that since Bobo's car is super-fast, traveling on the roads costs him
no time.
Formally, if
f(t) is the minimum money he should pay from city 1 to city
n at time
t, Bobo would like to find
Input
The first line contains 3 integers n,m,T (2≤n≤10,1≤m≤n(n-1),1≤T≤10
4).
The i-th of the following m lines contains 4 integers a
i,b
i,c
i,d
i (1≤a
i,b
i≤n,a
i≠b
i,0≤c
i,d
i≤10
3).
It is guaranteed that Bobo is able to drive from city 1 to city n.
Output
A floating number denotes the answer. It will be considered correct if its absolute or relative error does not exceed 10
-6.
Sample Input
3 3 2 1 2 1 0 2 3 1 0 1 3 1 1 3 3 2 1 2 1 0 2 3 1 0 1 3 0 5
Sample Output
1.75000000 2.00000000
Hint
Source
湖南省第十二届大学生计算机程序设计竞赛题意:城市之间有n个城市和m个单向道路。 第i条路从城市a[i]到城市b[i]。 对于每对城市u和v,最多有一条从u到v的道路。随着交通量越来越大,道路的费用也有所不同。 在时间t,应该支付(ci⋅t+ di)美元以沿着第i条路行驶。一个在一号城市的人想去第n个城市。 他想知道他必须花费的平均金额,他从t∈[0,T]的城市1开始。因为车速是超快的,通过道路不会花费时间。f(t)是他在时间t从城市1到城市n应该支付的最小钱
解题思路:最短路,自适应Simpson积分。
有这样一个积分公式:这个东西用于计算不方便直接积分的时候的近似积分。
由于直接套公式会与实际有很大偏差,有一个改进:
要求[L,R]的积分,先令m=(L+R)/2,根据上面的公式,求出[L,R]的公式值s0,以及[L,m]的公式值s1,[m,R]的公式值s2。
如果s0与 s1+s2 很接近,那么可以认为[L,R]的积分就是s0;否则进行递归,分别求[L,m]的积分和[m,R]的积分。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <vector>
#include <set>
#include <bitset>
#include <stack>
#include <map>
#include <climits>
#include <functional>
using namespace std;
#define LL long long
const int INF=0x3f3f3f3f;
const double eps=1e-8;
int n,m,t;
int s[20],nt[200],e[200],c[200],d[200],cnt;
int visit[20];
double dis[20];
double SPFA(double x)
{
for(int i=0;i<=n;i++) dis[i]=1.0*INF;
memset(visit,0,sizeof visit);
queue<int>q;
visit[1]=1;
q.push(1);
dis[1]=0;
while(!q.empty())
{
int pre=q.front();
q.pop();
visit[pre]=0;
for(int i=s[pre];~i;i=nt[i])
{
if(dis[pre]+c[i]*x+d[i]<dis[e[i]])
{
dis[e[i]]=dis[pre]+c[i]*x+d[i];
if(!visit[e[i]])
{
visit[e[i]]=1;
q.push(e[i]);
}
}
}
}
return dis[n];
}
double get(double L,double R)
{
return (R-L)*(SPFA(L)+4*SPFA((L+R)/2)+SPFA(R))/6;
}
double Ans(double L,double R)
{
double mid=(L+R)/2;
double s0=get(L,R),s1=get(L,mid),s2=get(mid,R);
if(fabs(s0-(s1+s2))<=eps) return s0;
else return Ans(L,mid)+Ans(mid,R);
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&t))
{
memset(s,-1,sizeof s);
cnt=1;
for(int i=1;i<=m;i++)
{
int u,v,cc,dd;
scanf("%d%d%d%d",&u,&v,&cc,&dd);
nt[cnt]=s[u],e[cnt]=v,c[cnt]=cc,d[cnt]=dd,s[u]=cnt++;
}
printf("%.8lf\n",Ans(0,1.0*t)/t);
}
return 0;
}