题目

现在,保密成为一个很重要也很困难的问题。如果没有做好,后果是严重的。比如,有个人没有自己去修电脑,又没有拆硬盘,后来的事大家都知道了。

当然,对保密最需求的当然是军方,其次才是像那个人。为了应付现在天上飞来飞去的卫星,军事基地一般都会建造在地下。

某K国的军事基地是这样子的:地面上两排大天井共n1个作为出入口,内部是许多除可以共享出入口外互不连通的空腔,每个空腔有且只有两个出入口,并且这两个出入口不会在同一排。为了方便起见,两排出入口分别编号为1,3,5…和2,4,6…并且最大的编号为n1。

虽然上面扯了那么多关于保密的东西,但是其实解密也是一件很纠结的事情。但其实最简单直接暴力无脑的解密方法就是找个人去看看。。。

我们有很牛X的特种部队,只需要派出一支特种部队到K国基地的某个出入口,那么和这个出入口直接相连的所有空腔都可以被探索,但也只有这些空腔可以被这支部队探索。现在有足够多的特种部队可以供你调遣,你必须使用他们调查完所有的K国基地内的空腔。

当然,你的基地离K国基地不会太近,周边的地图将会给你,表示为n个检查点和m条连接这些点的道路,其中点1到点n1就是K国基地的出入口,点n是你的部队的出发点。对每条道路,有不同的通行时间t和安全系数s。因为情报部门只对单向的道路安全系数进行了评估,所以这些道路只允许单向通行,并且不会存在环。

一支特种部队从你的基地出发,通过某条路径,到达某个K国基地出入口,此时这支部队的危险性表示为总时间和这条路径经过的所有道路的安全系数和的比值。整个行动的危险性表示为你派出的所有部队的危险性之和。你需要使这个值最小的情况下探索整个K国基地。

快点完成这个任务,在K国的叫兽宣布你是K国人之前。

输入格式

第一行2个正整数n,m (4 <= n <= 700, m <= 100000) 表示整个地区地图上的检查点和道路数。

下面m行,每行4个正整数a, b, t, s(a, b <=n, 1 <= t, s <= 10)表示一条从a到b的道路需时为t,安全系数为s。

接下来1行2个正整数m1和n1(m1 <= 40000, n1 < min{n, 161}), m1表示K国基地空腔的个数,n1表示K国基地出入口的个数。

再接下来m1行,每行2个正整数u, v (u, v<=n1, u是奇数,v是偶数),表示每个空腔的2个出入口。

输出格式

一行,最小的危险性,保留一位小数。或者输出”-1”(无引号)表示此任务不可能完成。

输入样例

5 5

5 1 10 1

5 1 10 1

5 2 9 1

5 3 7 1

5 4 8 1

4 4

1 2

1 4

3 2

3 4

输出样例

17.0

题解

每个空腔有两个入口,二者必选一

显然到达每个点都是有一个固定的最优代价

显然这就是一个最小边权覆盖,用网络流即可

现在问题转化为了求\(n1\)中每个点的最小代价

比值最小,显然是\(01\)分数规划

我们二分那个最小值,用SPFA判一下是否是负的就好了

【剪枝】在SPFA过程中,如果那个点的最短路已经为负,直接返回

QAQ二分边界设错了查了半天

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define eps 1e-9
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 705,maxm = 200005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
struct FLOW{
int to[maxm],nxt[maxm],ne,h[maxn],cur[maxn],vis[maxn],d[maxn],S,T;
double f[maxm];
FLOW(){ne = 2;}
void build(int u,int v,double w){
to[ne] = v; nxt[ne] = h[u]; f[ne] = w; h[u] = ne++;
to[ne] = u; nxt[ne] = h[v]; f[ne] = 0; h[v] = ne++;
}
bool bfs(){
queue<int> q;
memset(d,0,sizeof(d));
memset(vis,0,sizeof(vis));
int u,t;
q.push(S); d[S] = 0; vis[S] = true;
while (!q.empty()){
u = q.front(); q.pop();
for (int k = h[u]; k; k = nxt[k]){
if (fabs(f[k]) > eps && !vis[t = to[k]]){
d[t] = d[u] + 1; vis[t] = true;
if (t == T) return true;
q.push(t);
}
}
}
return vis[T];
}
double dfs(int u,double minf){
if (fabs(minf) < eps || u == T) return minf;
int t;
double ff,flow = 0;
if (cur[u] == -1) cur[u] = h[u];
for (int& k = cur[u]; k; k = nxt[k])
if (d[t = to[k]] == d[u] + 1 && fabs(ff = dfs(t,min(minf,f[k]))) > eps){
f[k] -= ff; f[k ^ 1] += ff;
flow += ff; minf -= ff;
if (fabs(minf) < eps) break;
}
return flow;
}
double maxflow(){
double flow = 0;
while (bfs()){
for (int i = 0; i <= T; i++) cur[i] = -1;
flow += dfs(S,INF);
}
return flow;
}
}G;
int h[maxn],ne = 2;
struct EDGE{int to,nxt; double t,s;}ed[maxm];
inline void build(int u,int v,double t,double s){
ed[ne] = (EDGE){v,h[u],t,s}; h[u] = ne++;
}
int n,m,n1,m1,reach[maxn],inq[maxn];
double ri[maxn],d[maxn];
void bfs(){
queue<int> q;
q.push(n); reach[n] = true;
int u;
while (!q.empty()){
u = q.front(); q.pop();
Redge(u) if (!reach[to = ed[k].to]){
reach[to] = true;
q.push(to);
}
}
}
bool spfa(double e,int T){
queue<int> q; q.push(n);
for (int i = 1; i < n; i++) d[i] = INF,inq[i] = false;
d[n] = 0;
int u;
while (!q.empty()){
u = q.front(); q.pop();
inq[u] = false;
Redge(u) if (d[to = ed[k].to] > d[u] + (ed[k].t - e * ed[k].s)){
d[to] = d[u] + (ed[k].t - e * ed[k].s);
if (to == T && d[to] <= eps) return true;
if (!inq[to]) inq[to] = true,q.push(to);
}
}
return d[T] < eps;
}
void work1(){
for (int i = 1; i <= n1; i++){
if (!reach[i]){
ri[i] = INF;
continue;
}
double l = 0,r = 1000,mid;
while (r - l > 0.00001){
mid = (l + r) / 2;
if (spfa(mid,i)) r = mid;
else l = mid;
}
ri[i] = (l + r) / 2;
}
}
int main(){
n = read(); m = read();
int u,v,t,s;
while (m--){
u = read(); v = read(); t = read(); s = read();
build(u,v,t,s);
}
bfs();
m1 = read(); n1 = read();
work1();
G.S = 0; G.T = n1 + 1;
for (int i = 1; i <= n1; i++)
if (i & 1) G.build(G.S,i,ri[i]);
else G.build(i,G.T,ri[i]);
for (int i = 1; i <= m1; i++){
u = read(); v = read();
if (v & 1) swap(u,v);
if (!reach[u] && !reach[v]){
puts("-1");
return 0;
}
G.build(u,v,INF);
}
printf("%.1lf\n",G.maxflow());
return 0;
}

BZOJ2285 [SDOI2011]保密 【01分数规划 + 网络流】的更多相关文章

  1. 【BZOJ2285】[SDOI2011]保密(分数规划,网络流)

    [BZOJ2285][SDOI2011]保密(分数规划,网络流) 题面 BZOJ 洛谷 题解 首先先读懂题目到底在干什么. 发现要求的是一个比值的最小值,二分这个最小值\(k\),把边权转换成\(t- ...

  2. 【洛谷P2494】 [SDOI2011]保密(分数规划+最小割)

    洛谷 题意: 题意好绕好绕...不想写了. 思路: 首先类似于分数规划做法,二分答案得到到每个点的最小危险度. 然后就是在一个二分图中,两边撤掉最少的点(相应代价为上面算出的危险度)及相应边,使得中间 ...

  3. 洛谷2494 [SDOI2011]保密 (分数规划+最小割)

    自闭一早上 分数规划竟然还能被卡精度 首先假设我们已经知道了到每个出入口的时间(代价) 那我们应该怎么算最小的和呢? 一个比较巧妙的想法是,由于题目规定的是二分图. 我们不妨通过最小割的形式. 表示这 ...

  4. bzoj 1312: Hard Life 01分数规划+网络流

    题目: Description 在一家公司中,人事部经理与业务部经理不和.一次,总经理要求人事部从公司的职员中挑选出一些来帮助业务部经理完成一项任务.人事部经理发现,在公司的所有职员中,有一些人相处得 ...

  5. [转]01分数规划算法 ACM 二分 Dinkelbach 最优比率生成树 最优比率环

    01分数规划 前置技能 二分思想最短路算法一些数学脑细胞? 问题模型1 基本01分数规划问题 给定nn个二元组(valuei,costi)(valuei,costi),valueivaluei是选择此 ...

  6. bzoj 4501: 旅行 01分数规划+概率期望dp

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=4501 题解: 首先我们不考虑可以删除边的情况下,如何计算期望边数. 然后我们发现这是个有 ...

  7. POJ3621Sightseeing Cows[01分数规划 spfa(dfs)负环 ]

    Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9703   Accepted: 3299 ...

  8. ZOJ 2676 Network Wars ★(最小割算法介绍 && 01分数规划)

    [题意]给出一个带权无向图,求割集,且割集的平均边权最小. [分析] 先尝试着用更一般的形式重新叙述本问题.设向量w表示边的权值,令向量c=(1, 1, 1, --, 1)表示选边的代价,于是原问题等 ...

  9. POJ 2728 Desert King ★(01分数规划介绍 && 应用の最优比率生成树)

    [题意]每条路径有一个 cost 和 dist,求图中 sigma(cost) / sigma(dist) 最小的生成树. 标准的最优比率生成树,楼教主当年开场随手1YES然后把别人带错方向的题Orz ...

随机推荐

  1. 【转】iOS-生成Bundle包-引入bundle-使用bundle

    在我们使用第三方框架时,常常看到XXX.bundle的文件. 我们找到该文件,显示包内容,大致看到很多资源文件:图片.配置文本.XIB文件……   什么是Bundle文件? 简单理解,就是资源文件包. ...

  2. Trie入门讲解

    我们常常用Trie(也叫前缀树)来保存字符串集合.如下图所示就是一个Trie. 上图表示的字符串集合为$\{a,to,tea,ted,ten,i,in,inn \}$,每个单词的结束位置对应一个“单词 ...

  3. appium---常用的adb命令

    在测试android-app的时候,adb命令可以帮助我们解决许多问题 什么是adb Android Debug Bridge,我们一般简称为adb,主要存放在sdk安装目录下的platform-to ...

  4. Python面向对象进阶(二)

    Python面向对象进阶2.html :first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1 ...

  5. SD Card Formatter for Mac Download

    https://www.sdcard.org/downloads/formatter_4/eula_mac/ SDFormatter Mac版是一款Mac OS平台上的sd卡修复工具,SDFormat ...

  6. Web前端 优化方案

    1.减少Http请求  在一个页面中图片,CSS,JS可能N个,如果每个资源都去请求一次服务器的话,那么服务器就会为每个资源开一个线程来完成,这样的话对服务器的压力就很大了.所以解决的方法就是合并资源 ...

  7. CPL学习笔记(二)

    数组 数组(array) 声明通用格式为: typeName arrayName[arraySize]. arrayName指定元素数目,必须为整型常量或const值.(不能是变量) int a[3] ...

  8. 10GNU C语言函数调用

    6. C 函数调用机制概述 ​ 在 Linux 内核程序 boot/head.s 执行完基本初始化操作之后,就会跳转区执行 init/main.c 程序.那么 head.s 程序时如何把执行控制转交给 ...

  9. centos7.4进入单用户模式

    centos7.4进入单用户模式 1 - 在启动grub菜单,选择编辑选项启动 2 - 按键盘e键,来进入编辑界面 3 - 找到Linux 16的那一行,将ro改为rw init=/sysroot/b ...

  10. day14-推导式和生成器表达式

    1.推导式规则 [每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] ----------遍历之后挨个处理[满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素 ...