题意描述

Sightseeing Cows G

给定一张有向图,图中每个点都有点权 \(a_i\),每条边都有边权 \(e_i\)。

求图中一个环,使 “环上个点权之和” 除以 “环上各边权之和” 最大。输出最大值。

解释一下,原题目中并没有点明这是一个环,但是从:

奶牛们不会愿意把同一个建筑物参观两遍。

可以看出,不管怎么走,走环一定是最优的,因为重复走相当于无故增加分母。

算法分析

据说这是一道 0/1 分数规划的题目,但是其实可以用更加通俗易懂的方法来解释。

假设用 \(v_i,e_i(1\leq i\leq k)\) 分别表示环上的点权和边权。

那么显然题目就是要找到最大的 \(\frac{\sum^{k}_{i=1} v_i}{\sum^{k}_{i=1} e_i}\)。

利用二分答案,当 \(\sum^k_{i=1} (mid\times e_i-v_i)<0\) 时:\(mid<\frac{\sum^{k}_{i=1} v_i}{\sum^{k}_{i=1} e_i}\),令 \(l=mid\)。

反之,当 \(\sum^k_{i=1} (mid\times e_i-v_i)\geq 0\):\(mid\geq \frac{\sum^{k}_{i=1} v_i}{\sum^{k}_{i=1} e_i}\),令 \(r=mid\)。

那么就将 \(e(x,y)\) 转化为 \(mid\times e_i-a[x]\),利用 SPFA 判断是否有负环即可。

代码实现

应为题目不保证图的连通性,所以 SPFA 开始的时候将所有点都入队。

利用二分答案将最优解变为判定即可。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#define N 10010
#define M 50010
using namespace std; int n,m,a[N],head[N],cnt=0,sum[N];
bool vis[N];
double dis[N];
struct Edge{
int nxt,to,val;
}ed[N<<1]; int read(){
int x=0,f=1;char c=getchar();
while(c<'0' || c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' && c<='9') x=x*10+c-48,c=getchar();
return x*f;
} void add(int u,int v,int w){
ed[++cnt].nxt=head[u];
ed[cnt].to=v,ed[cnt].val=w;
head[u]=cnt;
return;
} bool chck(double mid){
queue<int>q;
for(int i=1;i<=n;i++){
q.push(i);
dis[i]=0,vis[i]=true,sum[i]=1;
}
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=false;
if(++sum[u]>=n) return true;
for(int i=head[u];i;i=ed[i].nxt){
int v=ed[i].to;
double w=ed[i].val;
if(dis[v]>dis[u]+(double)(mid*w-(double)a[u])){//注意一下 double 与 int
dis[v]=dis[u]+(double)(mid*w-(double)a[u]);
if(!vis[v]) q.push(v),vis[v]=true;
}
}
}
return false;
} int main(){
n=read(),m=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=m;i++){
int u=read(),v=read(),w=read();
add(u,v,w);
}
double l=0.0,r=1000010.0,mid,eps=1e-5;
while(r-l>eps){
mid=(l+r)/2;
if(chck(mid)) l=mid;
else r=mid;
}
printf("%.2lf",l);
return 0;
}

完结撒花

P2868 [USACO07DEC]Sightseeing Cows G的更多相关文章

  1. [USACO07DEC]Sightseeing Cows(负环,0/1分数规划)

    [USACO07DEC]Sightseeing Cows Description Farmer John has decided to reward his cows for their hard w ...

  2. 【洛谷P2868】Sightseeing Cows

    题目大意:给定一个 N 个点,M 条边的有向图,点有点权,边有边权,求该有向图中的一个环,使得环上点权和与环上边权和之比最大. 题解:0/1 分数规划思想,每次二分一个 mid,在新图上跑 spfa, ...

  3. [USACO07DEC]Sightseeing Cows

    嘟嘟嘟 这题好像属于01分数规划问题,叫什么最优比率生成环. 题目概括一下,就是求一个环,满足∑v[i] / ∑c[i]最大. 我们可以堆上面的式子变个型:令 x = ∑v[i] / ∑c[i],则x ...

  4. P2868 [USACO07DEC]观光奶牛Sightseeing Cows

    P2868 [USACO07DEC]观光奶牛Sightseeing Cows [](https://www.cnblogs.com/images/cnblogs_com/Tony-Double-Sky ...

  5. 洛谷P2868 [USACO07DEC]观光奶牛Sightseeing Cows

    P2868 [USACO07DEC]观光奶牛Sightseeing Cows 题目描述 Farmer John has decided to reward his cows for their har ...

  6. 【POJ3621】Sightseeing Cows

    Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8331   Accepted: 2791 ...

  7. POJ 3621 Sightseeing Cows(最优比例环+SPFA检测)

    Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10306   Accepted: 3519 ...

  8. Sightseeing Cows(最优比率环)

    Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8915   Accepted: 3000 ...

  9. 【POJ3621】Sightseeing Cows 分数规划

    [POJ3621]Sightseeing Cows 题意:在给定的一个图上寻找一个环路,使得总欢乐值(经过的点权值之和)/ 总时间(经过的边权值之和)最大. 题解:显然是分数规划,二分答案ans,将每 ...

随机推荐

  1. Python-嵌套列表变成普通列表

    如何把[1, 5, 6, [2, 7, [3, [4, 5, 6]]]]变成[1, 5, 6, 2, 7, 3, 4, 5, 6]? 思考: -- for循环每次都遍历列表一层 -- 把取出的单个值加 ...

  2. LeetCode刷题总结-动态规划篇

    本文总结LeetCode上有动态规划的算法题,推荐刷题总数为54道.具体考点分析如下图: 1.中心扩展法 题号:132. 分割回文串 II,难度困难 2.背包问题 题号:140. 单词拆分 II,难度 ...

  3. Blend学习之Loading加载动画

    介绍: Blend for visual studio 与 visual studio 是有区别的 两者虽然是IDEA 但是专注的方向是不同的,前者是专注UI后者专注业务逻辑,当然你要用blend f ...

  4. 059 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 06 增强型for循环

    059 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 06 增强型for循环 本文知识点:增强型for循环 增强型for循环格式 案例练习增强型for循环 数组名字 ...

  5. VS2015建立一个完整的c++工程:头文件.h 源文件.cpp,自动生成类

    https://blog.csdn.net/weixin_40539125/article/details/81430801 打开VS2015 ,新建VS win32工程,前面步骤很简单,不再阐述 下 ...

  6. matlab find函数使用语法

    find 找到非零元素的索引和值 语法: 1. ind = find(X) 2. ind = find(X, k) 3. ind = find(X, k, 'first') 4. ind = find ...

  7. try-finally的时候try里面带return

    最近学习的JVM小册中老师提了个问题: 最开始我觉得是1,结果程序跑出来是0,感到很疑惑,于是查看了下字节码: 从字节码可以看出: 0:定义变量0 1:将0存入本地变量表slot-0 2:加载slot ...

  8. nrf528xx bootloader 模块介绍

    1. bootloader 的基本功能: 启动应用 几个应用之间切换 初始化外设 nordic nrf52xxx的bootloader主要功能用来做DFU, 可以通过HCI, UART 或BLE通信的 ...

  9. day52 Pyhton 前端03

    内容回顾 块级标签: div p h 列表:ol;ul;dl 表格:table 行内标签: span a i/em b/strong u/del 行内块: input textarea img 其他: ...

  10. 你不知道的MySQL,以及MariaDB初体验

    MySQL 是一个跨世纪的伟大产品,它最早诞生于 1979 年,距今已经有 40 多年的历史了,而如今比较主流的 Java 语言也只是 1991 年才诞生的,也就是说 MySQL 要比 Java 的诞 ...