您的位置:首页 > 编程语言 > C语言/C++

C++——NOIP模拟题——葫芦

2017-03-11 15:06 423 查看


葫芦


题目描述

葫芦世界有 n 个葫芦,标号为 1~n 。n 个葫芦由 m 条藤连接,每条藤连接了两个葫芦,这些藤构成了一张有向无环图。Tom 爬过每条藤都会消耗一定的能量。
Tom 站在 1 号葫芦上(你可以认为葫芦非常大,可以承受Tom的体重),他想沿着藤爬到 n 号葫芦上,其中每个葫芦只经过一次。
Tom 找到一条路径,使得消耗的能量与经过的葫芦数的比值最小。


输入格式

输入第一行两个正整数 n,m,分别表示葫芦的个数和藤数。

接下来 m 行,每行三个正整数 u,v,w 描述一条藤,表示这条藤由 u 连向 v ,Tom 爬过这条藤需要消耗 w 点能量。


输出格式

输出一行一个实数,表示答案(误差不超过 10-3 )。


样例数据 1

输入

4 6 

1 2 1 

2 4 6 

1 3 2 

3 4 4 

2 3 3 

1 4 8
输出

2.000


备注

【样例说明】

有 4 种爬法:

1->4,消耗能量 8,经过 2 个葫芦,比值为 8/2=4。

1->2->4,消耗能量 1+6=7,经过 3 个葫芦,比值为 7/3≈2.33。

1->3->4,消耗能量 2+4=6,经过 3 个葫芦,比值为 6/3=2。

1->2->3->4,消耗能量 1+3+4=8,经过 4 个葫芦,比值为 8/4=2。

所以选第三种或第四种方案,答案为 2 。
【数据规模与约定】

对于所有数据,Tom 爬过每条藤消耗的能量不会超过 103 ,且一定存在一条从 1 到 n 的路径。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
const int nn=201;
const int mm=2001;
const double inf=1e20;
const double eps=1e-4;
struct edge
{
int v;
int next;
double w;
double x;
}e[mm];
int head[nn];
double dis[nn];
bool vis[nn];
queue<int> q;
int n,m,cnt=0;
inline int read()
{
int x=0,t=1;char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') t=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return t*x;
}
void add(int u,int v,double w)
{
e[++cnt].v=v;
e[cnt].x=w;
e[cnt].next=head[u];
head[u]=cnt;
}
bool spfa(double x)
{
for(int i=1;i<=cnt;i++) e[i].w=e[i].x-x;
for(int i=1;i<=n;i++) dis[i]=inf;
dis[0]=0;
q.push(0);
vis[0]=true;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u];i;i=e[i].next)
if(dis[u]+e[i].w<dis[e[i].v]-eps)
{
dis[e[i].v]=dis[u]+e[i].w;
if(!vis[e[i].v]) q.push(e[i].v),vis[e[i].v]=true;
}
}
return dis
<-eps;
}
int main(void)
{
int u,v,w;
n=read();
m=read();
for(int i=1;i<=m;i++)
{
u=read();
v=read();
w=read();
add(u,v,w);
}
add(0,1,0);
double l=0,r=1e3;
while(r-l>eps)
{
double mid=(l+r)/2.0;
if(spfa(mid)) r=mid;
else l=mid;
}
printf("%0.3f\n",l);
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言