BZOJ 1690 【USACO 2007 Dec奶牛观光】

来源:互联网 发布:revit软件视频教程 编辑:程序博客网 时间:2024/05/21 07:13

Description
作为对奶牛辛勤工作的回报,约翰决定带她们去附近的大城市玩一天。这个城市有L个景点,参观第i个景点会给奶牛带来Fi点欢乐度。第二天一早,奶牛可以自由选择从一个景点出发,约翰会负责开车把她们送到那里,但她们晚上必须回到这个景点和约翰汇合。

大城市里都是单行道,第i条道路从第L1i个建筑通向第L2i个建筑,走完需要Ti的时间。奶牛讨厌走路,定义一条游览线路的“欢乐指数”为参观这条线路上所有景点的欢乐度之和与花在路上的时间之和的比值。欢乐指数越大的线路越受欢迎。当然,参观同一景点两次不会带来双倍的欢乐。假设奶牛们至少参观两个景点,请帮她们找到一条欢乐指数最大的线路。

Input Format
第一行:两个用空格分开的整数:L和P,1 ≤ L ≤ 1000,2 ≤ P ≤ 5000

第二行到L + 1行:第i + 1行有一个整数Fi,1 ≤ Fi ≤ 1000

第L + 2行到L + P + 1行:第i + L + 1行有三个用空格分开的整数:L1i,L2j和Ti,1 ≤ L1i ≤ L,1 ≤ L2i ≤ L,1 ≤ Ti ≤ 1000

Output Format
第一行:输出一个实数,表示最大的欢乐指数,保留两位小数

Sample Input
5 7
30
10
10
5
10
1 2 3
2 3 2
3 4 5
3 5 2
4 5 5
5 1 3
5 2 2
Sample Output
6.00
Hint
(1 → 2 → 3 → 5 → 1,总乐趣值为60,花费在路上的时间为10)

【题目大意】求一个环的{点权和}除以{边权和},使得那个环在所有环中{点权和}除以{边权和}最大。
【题解】
最优比例环(比uva11090多了个点权)
∑(i=1,n)v[i]/∑(i=1,n)e[i]最大的环(n为环的点数),
即对于所有的环都有 ∑(i=1,n)(v[i])/∑(i=1,n)(e[i])<=ans
∑(i=1,n)(ans*e[i]-v[i]) >=0
二分答案 若mid < ans时,就存在环使得∑(i=1,n)(mid*e[i]-v[i])<0,即有负环(重构边权为mid*e[i]-v[i]); 若mid >=ans时,就对于所有的环∑(i=1,n)(mid*e[i]-v[i])>=0,即没有负权回路。 spfa验证负环


#include <iostream>#include <cstdlib>#include <cstdio>#include <algorithm>#include <cstring>#include <stack>#include <vector>#include <queue>#include <map>using namespace std;double a[1500],d[1500],l,r,mid,o;struct info  {    int ar,next;    double l;  }road[10005];int first[1500],i,j,k,m,num,n,q[1500],c[1500],f[1500],p1,q1;void add(int x,int y,double len)  {     num++;     road[num].ar=y;road[num].next=first[x];     road[num].l=len;first[x]=num;  }int spfa(double k)  {    int i,h,t,u,v;    memset(c,0,sizeof(c));    memset(f,0,sizeof(f));    for (i=1;i<=n;i++) d[i]=1e9;    t=1;h=0;q[1]=1;d[1]=0;f[1]=1;c[1]=1;    for (;h!=t;)      {        h++;if (h==1500) h=0;u=q[h];f[u]=0;        for (i=first[u];i;i=road[i].next)          {            v=road[i].ar;            if (d[u]+k*road[i].l-a[v]<d[v])               {                d[v]=d[u]+k*road[i].l-a[v];                if (!f[v])                  {                    t++;if (t==1500) t=0;                    q[t]=v;f[v]=1;c[v]++;                    if (c[v]>n) return 1;                  }              }          }       }    return 0;  }int main()  {    scanf("%d%d",&n,&m);r=0;l=0;    for (i=1;i<=n;i++) scanf("%lf",&a[i]),r+=a[i];    for (i=1;i<=m;i++)      {        scanf("%d%d%lf",&p1,&q1,&o);        add(p1,q1,o);      }    for (;r-l>1e-5;)      {        mid=(l+r)/2;        if (spfa(mid)) l=mid;else r=mid;       }     printf("%.2f",l);  }
0 0
原创粉丝点击