题目链接:
http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1806
题解:
首先先了解下什么是自适应辛普森, 贴一个dalao的博客:http://blog.csdn.net/u014800748/article/details/44343955
此题只要调用一次自适应辛普森公式就可以了,其中f(x)就是当前时间为x时,从点1到点n的最短路,可以用前向星+spfa搞定。
自适应辛普森的模板:
const int eps = 1e-6;
double cal(double l, double r)
{
return (r-l) * (f(l) + 4 * f((l+r)/2) + f(r))/6;
}
double simpson(double l, double r)
{
double h = (l+r)/2;
double s0 = cal(l,r),s1 = cal(l,h),s2 = cal(h,r);
if(fabs(s0 - (s1+s2)) <= eps)return s0;
else return simpson(l,h) + simpson(h,r);
}
链式前向星的模板:
struct edge
{
int to,next,ci,di;//next表示该边连接的下一条边,to表示该边的右结点,可以加额外变量存其他信息
}e[1000];
int head[1000];
int tot;
void add(int u,int v,int c,int d)
{
e[++tot].to = v;
e[tot].next = head[u];
e[tot].ci = c;
e[tot].di = d;
head[u] = tot;
}
memset(head,0,sizeof(head));tot=0;//每次计算的清空操作
for(int i = head[u];i;i = e[i].next)//访问以u为起点,所有以该点为起点的边
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int eps = 1e-6;
int n,m,t;
struct edge
{
int to,next,ci,di;
}e[1000];
int head[1000];
int tot;
void add(int u,int v,int c,int d)
{
e[++tot].to = v;
e[tot].next = head[u];
e[tot].ci = c;
e[tot].di = d;
head[u] = tot;
}
double dist[100];
int vis[100];
double spfa(double x)
{
for(int i=1;i<=n;i++) dist[i]=999999999999.0;
memset(vis,0,sizeof(vis));
dist[1] = 0;
queue <int> que;
que.push(1);
vis[1] = 1;
while(!que.empty())
{
int u = que.front();
que.pop();
for(int i = head[u];i;i = e[i].next)
{
if(dist[u] + e[i].ci * x + e[i].di < dist[e[i].to])
{
dist[e[i].to] = dist[u] + e[i].ci * x + e[i].di;
if(vis[e[i].to] == 0)
{
vis[e[i].to] = 1;
que.push(e[i].to);
}
}
}
vis[u] = 0;
}
return dist[n];
}
double cal(double l, double r)
{
return (r-l) * (spfa(l) + 4 * spfa((l+r)/2) + spfa(r))/6;
}
double simpson(double l, double r)
{
double h = (l+r)/2;
double s0 = cal(l,r),s1 = cal(l,h),s2 = cal(h,r);
if(fabs(s0 - (s1+s2)) <= eps)return s0;
else return simpson(l,h) + simpson(h,r);
}
int main()
{
while(~scanf("%d %d %d",&n, &m, &t))
{
memset(head,0,sizeof(head));tot=0;
for(int i = 0; i < m; i++)
{
int a,b,c,d;
scanf("%d %d %d %d", &a, &b, &c, &d);
add(a,b,c,d);
}
double ans = simpson(0,(double)t)/t;
printf("%.8f\n", ans);
}
return 0;
}
/*
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
*/