usaco 地震 && 奶牛观光
Usaco 地震:
Description
一场地震把约翰家的牧场摧毁了,坚强的约翰决心重建家园。约翰已经重建了N个牧场, 现在他希望能修建一些道路把它们连接起来。研究地形之后,约翰发现可供修建的道路有M 条。碰巧的是,奶牛们最近也成立一个工程队,专门从事修复道路。而然,奶牛们很有经济 头脑,如果无利可图,它们是不会干的。
奶牛们关注的是挣钱速度,即总利润和总施工时间的比值。约翰和奶牛达成了协议,奶 牛负责修建道路,将所有牧场连通,而约翰需要支付F元。每条道路都有自己的施工时间和 建造成本。连接两个相同的牧场的道路可能有多条。保证所有的牧场必定是可连通的,不过 也有可能一些道路的建造成本之和会超过F。
请帮助奶牛们选择修复哪些道路,才能使单位时间的利润最大?
Input Format
第一行:三个整数: N,M和F,1≤N≤400,1≤M≤10000,1≤F≤2×10^9
第二行到M+1行:第i +1行表示第i条道路的信息,有四个整数:Ui,Vi,Ci和Ti,Ui和Vi表示这条道路连接的牧场编号,Ci表示这条路的施工时间,Ti表示建造成本,1≤Ui≤N,1≤Vi≤N,1≤Ci≤2×10^9,1≤Ti≤2×10^9
Output Format
第一行:一个保留四位小数的浮点数,表示奶牛们能挣到的最大单位时间利润,如果奶 牛们无钱可赚,则输出0.0000
-------------------------------------------------------------------------------------
显然这题是求最优比率生成树,
对最优比率 k 而言 (∑t)*k=F-∑v
F=(∑t)*k+∑v=∑(t*k+v)
显然上面这个式子具有单调性,随 k 而单调递增
因此可以对 k 进行二分,
以 ( k*t +v ) 作为关键字做生成树
若∑(t*k+v)>F 下调 k 否则上调 k
Ps.注意精度问题,图图大神说 :二分的精度至少要比保留的小数位数多2位。例如这题要求保留到0.0001,那么二分的精度应该为0.000001
代码如下:
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<iostream>
#define O 0.00000001
#define LL long long
#define INF 2000000000
using namespace std;
struct Point{
int x,y;
double c,t;
}a[];
int f[],n,m;
double l,r,ans,F,mid;
bool cmp(const Point&X,const Point&Y){
return X.c+mid*X.t<Y.c+mid*Y.t;
}
int find(int u){
return f[u]==u ? f[u] : f[u]=find(f[u]);
}
bool check(long double lim){
sort(a+,a++m,cmp);
for(int i=;i<=n;i++) f[i]=i;
int tot=;
double temp=;
for(int i=;i<=m;i++)
if(find(a[i].x)!=find(a[i].y)){
f[find(a[i].x)]=f[find(a[i].y)];
temp+=a[i].c+mid*a[i].t;
++tot;
if(temp>F) return false ;
}
if(tot<n-) {
printf("0.000");
exit();
}
return true;
}
int main(){
scanf("%d%d%lf",&n,&m,&F);
for(int i=;i<=m;i++)
scanf("%d%d%lf%lf",&a[i].x,&a[i].y,&a[i].c,&a[i].t);
l=,r=F;
while(r-l>=O){
mid=(l+r)/;
if(check(mid)){
ans=mid;
l=mid+O;
} else r=mid-O;
}
printf("%.4lf",ans);
}
-------------------------------------------------------------------------------------
Usaco 奶牛观光:
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
第一行:输出一个实数,表示最大的欢乐指数,保留两位小数
-----------------------------------------------------------------
好把,这题是求最优比率最短路(环)( Usaco真是一站式服务- =)
最优比率 (∑t)*k=∑f => ∑(t*k-f)=0
和上一题一样,k 具有单调性,也显然可以二分
那如何判断这个环是否小于 0(负权环)
利用SPFA:
图图大神的方法是:
用edge[i]表示到i的最短路经过的边数,若边数 = N,则存在负权环
我用了种比较傻的:
time[i]表示该点被更新了几次,如果大于 n 显然存在负权环
图图大神还说:SPFA的使用十分灵活,经常配合动规使用,所以往往队列里的初始状态是不唯一的。
代码如下:
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<iostream>
#include<queue>
#define INF 999999999
#define N 5011
const double E=1e- ;
using namespace std;
queue <int> q;
int n,P;
int T,last[N],next[N],s[N];
double sum[N],t[N],l,r,mid,ans;
bool check(){
int time[N]; memset(time,,sizeof(time));
double d[N]; for(int i=;i<=n;i++) d[i]=INF;
bool in[N]; memset(in,,sizeof(in));
time[]=in[]=; d[]=;
while(!q.empty()) q.pop();
for(q.push();!q.empty();q.pop()){
int now=q.front();
for(int i=last[now];i;i=next[i]){
double w=t[i]*mid-sum[now];
if(d[s[i]]+E>d[now]+w){
d[s[i]]=d[now]+w;
if(!in[s[i]]){
in[s[i]]=;
q.push(s[i]);
if(++time[s[i]]>n) return ;
}
}
}
in[now]=;
}
return ;
}
int main(){
scanf("%d%d",&n,&P);
for(int i=;i<=n;i++) scanf("%lf",&sum[i]);
for(int i=;i<=P;i++){
int x,y;
double v;
scanf("%d%d%lf",&x,&y,&v);
next[++T]=last[x]; last[x]=T; s[T]=y; t[T]=v;
}
l=E,r=;
while(r-l>=E){
mid=(l+r)/;
if(check()){
ans=mid;
l=mid+E;
} else r=mid-E;
}
printf("%.2lf",ans);
}
usaco 地震 && 奶牛观光的更多相关文章
- 157. [USACO Nov07] 奶牛跨栏
157. [USACO Nov07] 奶牛跨栏(点击转到COGS) 输入文件:hurdles.in 输出文件:hurdles.out 时间限制:1 s 内存限制:128 MB 译 by CmY ...
- SPFA cojs 176. [USACO Feb07] 奶牛聚会
cojs 176. [USACO Feb07] 奶牛聚会 ★☆ 输入文件:sparty.in 输出文件:sparty.out 简单对比时间限制:3 s 内存限制:16 MB N(1 ≤ ...
- cogs 141. [USACO Jan08] 奶牛的选举
141. [USACO Jan08] 奶牛的选举 ★ 输入文件:elect.in 输出文件:elect.out 简单对比时间限制:1 s 内存限制:16 MB 在推翻了Farmer J ...
- 题解 [USACO Mar08] 奶牛跑步
[USACO Mar08] 奶牛跑步 Description Bessie准备用从牛棚跑到池塘的方法来锻炼. 但是因为她懒,她只准备沿着下坡的路跑到池塘,然后走回牛棚. Bessie也不想跑得太远,所 ...
- cogs157. [USACO Nov07] 奶牛跨栏 x
157. [USACO Nov07] 奶牛跨栏 ★★ 输入文件:hurdles.in 输出文件:hurdles.out 简单对比时间限制:1 s 内存限制:128 MB 译 by Cm ...
- 157. [USACO Nov07] 奶牛跨栏(第三次考试大整理)
157. [USACO Nov07] 奶牛跨栏 输入文件:hurdles.in 输出文件:hurdles.out 简单对比 时间限制:1 s 内存限制:128 MB 译 by CmYkRg ...
- cogs 176. [USACO Feb07] 奶牛聚会 dijkstra
176. [USACO Feb07] 奶牛聚会 ★☆ 输入文件:sparty.in 输出文件:sparty.out 简单对比时间限制:3 s 内存限制:16 MB 译: zqzas N ...
- [USACO]地震 (二分答案+最优比率生成树详解)
题面:[USACO 2001 OPEN]地震 题目描述: 一场地震把约翰家的牧场摧毁了, 坚强的约翰决心重建家园. 约翰已经重建了N个牧场,现在他希望能修建一些道路把它们连接起来.研究地形之后,约翰发 ...
- usaco 安慰奶牛
Description 约翰有N个牧场,编号依次为1到N.每个牧场里住着一头奶牛.连接这些牧场的有P条 道路,每条道路都是双向的.第j条道路连接的是牧场Sj和Ej,通行需要Lj的时间.两牧场之 间最多 ...
随机推荐
- 用Session实现验证码
新建一个 ashx 一般处理程序 如: YZM.ashx继承接口 IRequiresSessionState //在一般处理程序里面继承 HttpContext context 为请求上下文,包含此次 ...
- HTML5 声明兼容IE的写法
<!DOCTYPE html> <!–[if IE]> <meta http-equiv=”X-UA-Compatible” content=”IE=8″ /> & ...
- PHPUnit初试
先测试了一下加减,检查一下环境,又调用函数测试了服务器名. 源代码: class DemoController extends \Think\Controller { /** * @assert (5 ...
- yii2源码学习笔记(十一)
Controller控制器类,是所有控制器的基类,用于调用模型和布局. <?php /** * @link http://www.yiiframework.com/ * @copyright C ...
- C++ QT中的QSound使用方法
在pro文件中添加 QT += multimedia 就可以了
- leetcode 第九题 Palindrome Number(java)
Palindrome Number time=434ms 负数不是回文数 public class Solution { public boolean isPalindrome(int x) { in ...
- [HDOJ 5212] [BestCoder Round#39] Code 【0.0】
题目链接:HDOJ - 5212 题目分析 首先的思路是,考虑每个数对最终答案的贡献. 那么我们就要求出:对于每个数,以它为 gcd 的数对有多少对. 显然,对于一个数 x ,以它为 gcd 的两个数 ...
- NCPC 2012 Bread Sorting
逆序对数的应用: 逆序对数的写法有,二分,树状数组,分治: 学习一下: 树状数组版: 代码: #include<cstdio> #include<cstring> #inclu ...
- js template
http://garann.github.io/template-chooser/ http://www.gbin1.com/technology/javascript/20120917-javasc ...
- Android 获取手机联系人信息
//获取联系人 Uri rawContacts = Uri.parse("content://com.android.contacts/raw_contacts"); Conten ...