题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1806
解法:被积函数,就是用spfa跑出来的结果,然后掏出辛普森就可以 了。注意加的边是单向边。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200;
const double eps = 1e-8;
struct edge{
int v,next;
double c,d;
}E[maxn];
int head[20], edgecnt;
int n, m;
void init(){
memset(head,-1,sizeof(head));
edgecnt=0;
}
void add(int u,int v,double c, double d){
E[edgecnt].c=c,E[edgecnt].d=d,E[edgecnt].v=v,E[edgecnt].next=head[u],head[u]=edgecnt++;
}
double spfa(double x){
double dis[20];
bool vis[20];
for(int i=1; i<=n; i++) dis[i]=999999999999.0, vis[i]=0;
queue<int>q;
q.push(1);
dis[1]=0;
while(!q.empty())
{
int u=q.front(); q.pop(); vis[u]=0;
for(int i=head[u];i+1;i=E[i].next){
int v=E[i].v;
if(dis[v]-dis[u]-E[i].c*x-E[i].d>eps){
dis[v]=dis[u]+E[i].c*x+E[i].d;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
return dis[n];
}
double cal(double L, double R){
return (R-L)*(spfa(L)+4.0*spfa((L+R)/2)+spfa(R))/6.0;
}
double Simpon(double L, double R){
double mid=(L+R)/2.0;
double s0,s1,s2;
s0=cal(L,R);
s1=cal(L,mid);
s2=cal(mid,R);
if(fabs(s0-(s1+s2))<=eps) return s0;
else return Simpon(L,mid)+Simpon(mid,R);
}
int main()
{
int T;
while(~scanf("%d%d%d",&n,&m,&T)){
init();
for(int i=1; i<=m; i++){
int a,b;
double c,d;
scanf("%d %d %lf %lf",&a,&b,&c,&d);
add(a,b,c,d);
//add(b,a,c,d);
}
double ans=Simpon(0,1.0*T)/(1.0*T);
printf("%.8f\n", ans);
}
return 0;
}