题面:[HNOI2009]最小圈

题目描述:

考虑带权的有向图 $ G=(V,E) $ 以及 $ w:E\rightarrow R $ ,每条边 $ e=(i,j)(i\neq j,i\in V,j\in V) $ 的权值定义为 $ w_{i,j} $ ,令 $ n=|V| $ 。 $ c=(c_1,c_2,\cdots,c_k)(c_i\in V) $ 是 $ G $ 中的一个圈当且仅当 $ (c_i,c_{i+1})(1\le i\lt k) $ 和 $ (c_k,c_1) $ 都在 $ E $ 中,这时称 $ k $ 为圈 $ c $ 的长度同时令 $ c_{k+1}=c_1 $ ,并定义圈 $ c=(c_1,c_2,\cdots,c_k) $ 的平均值为 $ \mu(c)=\sum\limits_{i=1}^{k} w_{c_i,c_{i+1}}/k $ ,即 $ c $ 上所有边的权值的平均值。令 $ \mu'(c)=Min(\mu(c)) $ 为 $ G $ 中所有圈 $ c $ 的平均值的最小值。现在的目标是:在给定了一个图 $ G=(V,E) $ 以及 $ w:E\rightarrow R $ 之后,请求出 $ G $ 中所有圈 $ c $ 的平均值的最小值 $ \mu'(c)=Min(\mu(c)) $

输入格式:

第一行2个正整数,分别为 $ n $ 和 $ m $ ,并用一个空格隔开,只用 $ n=|V|,m=|E| $ 分别表示图中有 $ n $ 个点 $ m $ 条边。

接下来m行,每行3个数 $ i,j,w_{i,j} $ ,表示有一条边 $ (i,j) $ 且该边的权值为 $ w_{i,j} $ 。输入数据保证图 $ G=(V,E) $ 连通,存在圈且有一个点能到达其他所有点。

输出格式:

请输出一个实数 $ \mu'(c)=Min(\mu(c)) $ ,要求输出到小数点后8位。

输入样例#1:

4 5

1 2 5

2 3 5

3 1 5

2 4 3

4 1 3

输出样例#1:

3.66666667

输入样例#2:

2 2

1 2 -2.9

2 1 -3.1

输出样例#2:

-3.00000000

说明:

对于100%的数据, $ n\le 3000,m\le 10000,|w_{i,j}| \le 10^7 $



$ solution: $

这道题要我们求平均值的最小值,所以我们考虑二分答案的可能性,先列出答案的意义:

$ ans=\frac{\sum\limits_{i=1}^{k} w_{c_i,c_{i+1}}}{K}\quad _{(c_{k+1}=c_1)} $

我们将它转换一下:

$ ans\times k={\sum\limits_{i=1}^{k} w_{c_i,c_{i+1}}}\quad _{(c_{k+1}=c_1)} $

$ 0=\sum\limits_{i=1}^{k} (w_{c_i,c_{i+1}})-ans\times k\quad _{(c_{k+1}=c_1)} $

$ 0=\sum\limits_{i=1}^{k}(w_{c_i,c_{i+1}}-ans)\quad _{(c_{k+1}=c_1)} $

这样我们发现它已经化成了一个二分答案的常用等式(等式右边可以 $ O(n) $ 求出来,且具备单调性)而我们注意到等式左边为0,所以我们可以二分ans,并将边权改为 $ w_{c_i,c_{i+1}}-mid $ ,然后求负环即可。

为什么可以这样做呢?这个较地震那一题好讲一些,我们当前二分出来的平均值mid,我们将每一条边的边权都减去它,如果存在负环,说明这个环上所有边权实际边权值加起来的平均值一定小于mid!(这里需要仔细想一下)



$ code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set> #define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int using namespace std; const db cha=1e-9; struct su{
db v;int to,next;
}a[10005]; bool f;
int n,m,top;
int tou[3005];
bool vis[3005];
db mid,dis[3005]; inline int qr(){
char ch;
while((ch=getchar())<'0'||ch>'9');
int res=ch^48;
while((ch=getchar())>='0'&&ch<='9')
res=res*10+(ch^48);
return res;
} inline void add(int x,int y){
scanf("%lf",&a[++top].v);
a[top].to=y;
a[top].next=tou[x];
tou[x]=top;
} inline void spfa(int i){
vis[i]=1;
for(rg j=tou[i];j;j=a[j].next){
if(dis[a[j].to]>dis[i]+a[j].v-mid){
dis[a[j].to]=dis[i]+a[j].v-mid;
if(vis[a[j].to])return void(f=1);
else spfa(a[j].to);
}
}vis[i]=0;
} inline bool check(){
for(rg i=1;i<=n;++i)
dis[i]=vis[i]=0;;f=0;
for(rg i=1;i<=n&&!f;++i)
if(!vis[i])spfa(i);
return f;
} int main(){
freopen("cycle.in","r",stdin);
freopen("cycle.out","w",stdout);
n=qr(),m=qr();
for(rg i=1;i<=m;++i)
add(qr(),qr());
db l=-1e7,r=1e7;
while(l<=r){
mid=(l+r)/2;
if(check())r=mid-cha;
else l=mid+cha;
}printf("%.8lf\n",l);
return 0;
}

[HNOI2009]最小圈 (二分答案+负环)的更多相关文章

  1. BZOJ 1486: [HNOI2009]最小圈( 二分答案 + dfs判负圈 )

    二分答案m, 然后全部边权减掉m, 假如存在负圈, 那么说明有平均值更小的圈存在. 负圈用dfs判断. ------------------------------------------------ ...

  2. bzoj 1486: [HNOI2009]最小圈 dfs求负环

    1486: [HNOI2009]最小圈 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1022  Solved: 487[Submit][Status] ...

  3. 递归型SPFA+二分答案 || 负环 || BZOJ 4773

    题解: 基本思路是二分答案,每次用Dfs型SPFA验证该答案是否合法. 一点细节我注释在代码里了. 代码: #include<cstdio> #include<cstring> ...

  4. [HNOI2009]最小圈 分数规划 spfa判负环

    [HNOI2009]最小圈 分数规划 spfa判负环 题面 思路难,代码简单. 题目求圈上最小平均值,问题可看为一个0/1规划问题,每个边有\(a[i],b[i]\)两个属性,\(a[i]=w(u,v ...

  5. BZOJ_1486_[HNOI2009]最小圈_01分数规划

    BZOJ_1486_[HNOI2009]最小圈_01分数规划 Description Input Output Sample Input 4 5 1 2 5 2 3 5 3 1 5 2 4 3 4 1 ...

  6. bzoj千题计划227:bzoj1486: [HNOI2009]最小圈

    http://www.lydsy.com/JudgeOnline/problem.php?id=1486 二分答案 dfs版spfa判负环 #include<queue> #include ...

  7. 【BZOJ1486】[HNOI2009]最小圈 分数规划

    [BZOJ1486][HNOI2009]最小圈 Description Input Output Sample Input 4 5 1 2 5 2 3 5 3 1 5 2 4 3 4 1 3 Samp ...

  8. BZOJ1486 HNOI2009 最小圈 【01分数规划】

    BZOJ1486 HNOI2009 最小圈 Description 应该算是01分数规划的裸板题了吧..但是第一次写还是遇到了一些困难,vis数组不清零之类的 假设一个答案成立,那么一定可以找到一个环 ...

  9. 【算法】01分数规划 --- HNOI2009最小圈 & APIO2017商旅 & SDOI2017新生舞会

    01分数规划:通常的问法是:在一张有 \(n\) 个点,\(m\) 条边的有向图中,每一条边均有其价值 \(v\) 与其代价 \(w\):求在图中的一个环使得这个环上所有的路径的权值和与代价和的比率最 ...

随机推荐

  1. 注册页面手机验证码无跳转接收[html+js+ajax+php]

    [学习笔记] 来源:注册时需要使用短信验证码,但是注册的时候,点击接收验证码时,会产生跳转(尼玛,这不是我想要的啊!o(╥﹏╥)o) 查询资料和看书之后,知道使用js+ajax可以实现,就从网上找了一 ...

  2. pdo连接的时候设置字符编码是这样的

    $pdo = new \PDO(..,..,..) $pdo->query('SET NAMES utf8mb4'); $pdo->exex('sql....');

  3. Android8.0运行时权限策略变化和适配方案

    版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.comAndroid8.0也就是Android O即将要发布了,有很多新特性,目前我们可以通过AndroidS ...

  4. BZOJ 1195: [HNOI2006]最短母串

    1195: [HNOI2006]最短母串 Time Limit: 10 Sec  Memory Limit: 32 MBSubmit: 1346  Solved: 450[Submit][Status ...

  5. 用DotNetOpenAuth实现基于OAuth 2.0的web api授权 (一)Getting Start

    1. 下载 源码下载 2. build solution,创建虚拟目录: 右健MyContatacts/MyPromo项目,选择Properties,点击左边的Web,点击 Create Virtua ...

  6. luoguU38228 签到题 (BSGS)

    签到一脸 $a_n=10a_{n-1}+1$求出通项$a_n=\frac{10^n-1}{9}$,然后可以化成$10^n=9K+1 (mod m)$,求一个最小的n 然后我们知道这个n一定是<= ...

  7. Python进制表示及转换

    进制表示: 二进制:>>> abin = 0b1000>>> abin8 八进制:>>> aoct = 0o123 (数字0,字母o)>&g ...

  8. 在kubernetes集群上用helm安装Datadog(Monitoring)

    Datadog is a monitoring service that gathers monitoring data from your containers within your Azure ...

  9. 洛谷 P1417烹调方案

    题目大意: 一共有n件食材,每件食材有三个属性,ai,bi和ci,如果在t时刻完成第i样食材则得到ai-t*bi的美味指数,用第i件食材做饭要花去ci的时间. 求最大美味指数之和. 分析: 显然的0/ ...

  10. 求n(n>=2)以内的质数/判断一个数是否质数——方法+细节优化

    #include <stdio.h> #include <stdlib.h> //判断i是否质数,需要判断i能否被(long)sqrt(i)以内的数整除 //若i能被其中一个质 ...