题意:

给定L个点, P条边的有向图, 每个点有一个价值, 但只在第一经过获得, 每条边有一个花费, 每次经过都要付出这个花费, 在图中找出一个环, 使得价值之和/花费之和 最大

分析:

这道题其实并不是很好想, 因为价值和花费不是在同一样东西, 价值是点, 花费是边。

但回到我们要求的问题上, 我们要找出一个最优比率的环, 那么其实每个点只会经过一次, 是一个单独的环, 所以我们可以把价值也视为边的一部分。

参考这篇博客http://blog.csdn.net/gengmingrui/article/details/47443705

用01分数划分的套路构造出

然后二分这个L, 如果这个L值跑spfa最长路存在正权环路, 说明了L太小, 存在更优的F(L), 没有正权环路, 说明L太大, 一直二分即可有答案。

这题的坑就是没有特判, 输出3个小数位一直在找错。

SPFA

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstring>
#include <cmath>
#include <iomanip>
#define rep(i,a,b) for(int i = a; i < b;i++)
#define _rep(i,a,b) for(int i = a; i <= b;i++)
using namespace std;
const double eps = 1e-;
const double inf = 1e9 + ;
const int maxn = + ;
int n , m;
double val[maxn];
struct edge{
int to;
double d;
edge(int _to, double _d): to(_to), d(_d){}
};
vector<edge> G[maxn];
bool spfa(double L){ //因为答案最终一定是一个环,所以我们将每一条边的收益规定为其终点的收益,这样一个环上所有的花费和收益都能够被正确的统计。
double dis[maxn];
bool vis[maxn];
int enter_cnt[maxn];//记录入队次数
fill(dis, dis+maxn, -inf);//求最长路初始化为 负无穷
memset(vis, , sizeof(vis));
memset(enter_cnt, , sizeof(enter_cnt));
queue<int> q;
vis[] = ;
dis[] = ;
enter_cnt[]++;//第一次进队也要记录
q.push(); while(!q.empty()){
int u = q.front();
for(int i = ; i < G[u].size(); i++){ //求一个最长路的正权环路
int v = G[u][i].to;
double d = G[u][i].d;
double w = val[v] - L * d;
if(dis[v] < dis[u] + w){
dis[v] = dis[u] + w;
if(!vis[v]){
if(++enter_cnt[v] >= n) return true;
vis[v] = ;
q.push(v);
}
}
}
vis[u] = ;
q.pop();
}
return false;
}
int main(){
// freopen("1.txt","r", stdin);
while(cin >> n >> m){
_rep(i,,n) cin >> val[i];
rep(i,,m){
int u, v, d;
cin >> u >> v >> d;
G[u].push_back(edge(v,d));
}
double l = , r = 10000.0;
while(abs(r - l) > eps){
double mid = (l+r)/;
if(spfa(mid)) //如果有环路, L太小了
{
l = mid;
}
else r = mid;
}
cout.setf(ios::fixed);
cout << setprecision() << l << "\n";
_rep(i,,n) G[i].clear();
}
return ;
}

Bellman

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstring>
#include <cmath>
#include <iomanip>
#define rep(i,a,b) for(int i = a; i < b;i++)
#define _rep(i,a,b) for(int i = a; i <= b;i++)
using namespace std;
const double eps = 1e-;
const double inf = 1e9 + ;
const int maxn = + ;
int n , m;
double val[maxn];
struct edge{
int to , d;
edge(int _to, int _d): to(_to), d(_d){}
};
vector<edge> G[maxn];
bool Bellman(double L){ //因为答案最终一定是一个环,所以我们将每一条边的收益规定为其终点的收益,这样一个环上所有的花费和收益都能够被正确的统计。
double dis[maxn];
fill(dis, dis+maxn, -inf); for(int times = ; times < n - ; times++) //进行n - 1轮松弛
{
int flag = ;
for(int u = ; u <= n; u++){
for(int i = ; i < G[u].size(); i++){
int v = G[u][i].to;
double d = G[u][i].d;
double w = val[v] - L * d;
if(dis[v] < dis[u] + w){
flag = ;
dis[v] = dis[u] + w;
}
}
}
if(!flag) return false;//如果n-1次松弛前已经没有松弛, 肯定不存在正权环路
}
for(int u = ; u <= n; u++){
for(int i = ; i < G[u].size(); i++){
int v = G[u][i].to;
double d = G[u][i].d;
double w = val[v] - L * d;
if(dis[v] < dis[u] + w){
return true;
}
}
}
return false;
}
int main(){
// freopen("1.txt","r", stdin);
while(cin >> n >> m){
_rep(i,,n) cin >> val[i];
rep(i,,m){
int u, v, d;
cin >> u >> v >> d;
G[u].push_back(edge(v,d));
}
double l = , r = 10000.0;
while(abs(l - r) > eps){
double mid = (l+r)/;
if(Bellman(mid)) //如果有环路, L太小了
{
l = mid;
}
else r = mid;
}
cout.setf(ios::fixed);
cout << setprecision() << l << "\n";
_rep(i,,n) G[i].clear();
}
return ;
}

POJ 3621 Sightseeing Cows (最优比率环 01分数划分)的更多相关文章

  1. POJ 3621 Sightseeing Cows [最优比率环]

    感觉去年9月的自己好$naive$ http://www.cnblogs.com/candy99/p/5868948.html 现在不也是嘛 裸题,具体看学习笔记 二分答案之后判负环就行了 $dfs$ ...

  2. POJ3621 Sightseeing Cows 最优比率环 二分法

    题目链接:http://poj.org/problem?id=3621 Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total ...

  3. POJ3621 Sightseeing Cows(最优比率环)

    题目链接:id=3621">http://poj.org/problem?id=3621 在一个有向图中选一个环,使得环上的点权和除以边权和最大.求这个比值. 经典的分数规划问题,我认 ...

  4. POJ 3621 Sightseeing Cows 【01分数规划+spfa判正环】

    题目链接:http://poj.org/problem?id=3621 Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total ...

  5. [POJ 3621] Sightseeing Cows

    [题目链接] http://poj.org/problem?id=3621 [算法] 01分数规划(最优比率环) [代码] #include <algorithm> #include &l ...

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

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

  7. POJ 3621 Sightseeing Cows (bellman-Ford + 01分数规划)

    题意:给出 n 个点 m 条有向边,要求选出一个环,使得这上面 点权和/边权和 最大. 析:同样转成是01分数规划的形式,F / L 要这个值最大,也就是 G(r) = F - L * r 这个值为0 ...

  8. POJ 2728 Desert King(最优比率生成树 01分数规划)

    http://poj.org/problem?id=2728 题意: 在这么一个图中求一棵生成树,这棵树的单位长度的花费最小是多少? 思路: 最优比率生成树,也就是01分数规划,二分答案即可,题目很简 ...

  9. POJ 3621 Sightseeing Cows 01分数规划,最优比例环的问题

    http://www.cnblogs.com/wally/p/3228171.html 题解请戳上面 然后对于01规划的总结 1:对于一个表,求最优比例 这种就是每个点位有benefit和cost,这 ...

随机推荐

  1. java 丢失的异常

    采用finally从句中的,可能会丢失异常 package thinking; //: LostMessage.java // How an exception can be lost class V ...

  2. Caffe实战二(手写体识别例程:CPU、GPU、cuDNN速度对比)

    上一篇文章成功在CPU模式下编译了Caffe,接下来需要运行一个例程来直观的了解Caffe的作用.(参考:<深度学习 21天实战Caffe>第6天 运行手写体数字识别例程) 编译步骤: C ...

  3. python之yaml模块和ddt模块

    aml文件是专门用来写配置文件的语言,非常简洁和强大,远比json格式方便. 在PC中新建一个yml/yaml为为缩略名的文件,输入信息见下图 新建一个py文件处理yml文件,直接处理成字典格式 缩进 ...

  4. [转]2010 Ruby on Rails 書單 與 練習作業

    原帖:http://wp.xdite.net/?p=1754 ========= 學習 Ruby on Rails 最快的途徑無非是直接使用 Rails 撰寫產品.而這個過程中若有 mentor 指導 ...

  5. Redis学习笔记1-安装配置

    一.Redis安装 Redis官网:http://www.redis.io/download 注意:版本号2.4,2.6,2.8等偶数结尾为稳定版,2.5等为非稳定版本,生成环境应该使用稳定版 下载解 ...

  6. UOJ#52. 【UR #4】元旦激光炮(交互)

    题意 给出三个已经排好序的数组$a, b, c$ 在$100$次询问内找出第$k$小的元素 Sol 一种很显然的$log^2n$的做法:首先在$a$中二分,然后再$b,c$中二分.这样可以得到$60$ ...

  7. ES6—带默认值的函数参数及其作用域

    在学习ES6函数一章时,发现了一个有意思的现象,原文描述如下: 这段话主要state了3个事实: ①函数参数有默认值时,会在声明初始化阶段形成一个单独的作用域 ②这个作用域在初始化结束后消失 ③没默认 ...

  8. new操作符具体干了什么

    function Func(){ }; var newFunc=new Func (); new共经过了4个阶段 1.创建一个空对象 var obj=new Object(); 2.设置原型链 把 o ...

  9. IOS存储目录documents你在哪里啊

    iphone沙箱模型的有四个文件夹,分别是什么,永久数据存储一般放在什么位置,得到模拟器的路径的简单方式是什么. documents,tmp,app,Library. (NSHomeDirectory ...

  10. linux环境iptables配置

    Linux iptables常用规则 设置一个自己用的表, 允许ping 允许ssh 允许 web 允许mysql 允许 ftp 允许dns查询 其他的拒绝.脚本如下 # Firewall confi ...