题意:
就是一个积分+最短路
分析:
学到的新知识:自适应
Simpson
积分
∫baf(x)dx≈F(a,b)=(b−a)6[f(a)+4f(a+b2)+f(b)]
如果 F(a,a+b2)+F(a+b2,b) 越接近 F(a,b) ,那么 F(a,b) 越接近 ∫baf(x)dx
那么就是暴力最短路+二分就行了。
代码:
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
const double inf = 1000000000.0;
int n,m,T;
int head[12],edge_cnt;
struct Edge{
int nt,to;
int c,d;
}edge[220];
void addedge(int u,int v,int c,int d){
edge[edge_cnt].to = v;
edge[edge_cnt].c = c;
edge[edge_cnt].d = d;
edge[edge_cnt].nt = head[u];
head[u] = edge_cnt ++;
}
double dp[12];
struct Node{
int x;
double val;
Node(){}
Node(double a,int b) : val(a),x(b) {}
bool operator < (const Node &rhs) const{
return val > rhs.val;
}
};
double dij(int st,double t){
for(int i = 1;i <= n;++ i) dp[i] = inf;
dp[st] = 0.0;
priority_queue <Node> q;
q.push(Node(0.0,1));
while(!q.empty()){
Node a = q.top(); q.pop();
int u = a.x;
if(a.val != dp[u]) continue;
for(int i = head[u];i != -1;i = edge[i].nt){
int v = edge[i].to;
double tem = edge[i].c*t+edge[i].d;
if(dp[v] > tem+dp[u]){
dp[v] = tem+dp[u];
q.push(Node(dp[v],v));
}
}
}
return dp[n];
}
double calc(double l,double r){
double mid = (l+r)/2;
double t1 = dij(1,l);
double t2 = dij(1,mid);
double t3 = dij(1,r);
return (r-l)*(t1+4*t2+t3)/6;
}
double work(double l,double r){
double mid = (l+r)/2;
double s1 = calc(l,mid);
double s2 = calc(mid,r);
double s3 = calc(l,r);
if(fabs(s3-s1-s2) < eps) return s3;
return work(l,mid)+work(mid,r);
}
int main(){
//freopen("test.in","r",stdin);
while(~scanf("%d%d%d",&n,&m,&T)){
edge_cnt = 0;
memset(head,-1,sizeof(head));
for(int i = 0;i < m;++ i){
int u,v,c,d;
scanf("%d%d%d%d",&u,&v,&c,&d);
addedge(u,v,c,d);
}
printf("%.8f\n",work(0.0,T*1.0)/T);
}
return 0;
}