BZOJ2285 [SDOI2011]保密 【01分数规划 + 网络流】
题目
现在,保密成为一个很重要也很困难的问题。如果没有做好,后果是严重的。比如,有个人没有自己去修电脑,又没有拆硬盘,后来的事大家都知道了。
当然,对保密最需求的当然是军方,其次才是像那个人。为了应付现在天上飞来飞去的卫星,军事基地一般都会建造在地下。
某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分数规划 + 网络流】的更多相关文章
- 【BZOJ2285】[SDOI2011]保密(分数规划,网络流)
[BZOJ2285][SDOI2011]保密(分数规划,网络流) 题面 BZOJ 洛谷 题解 首先先读懂题目到底在干什么. 发现要求的是一个比值的最小值,二分这个最小值\(k\),把边权转换成\(t- ...
- 【洛谷P2494】 [SDOI2011]保密(分数规划+最小割)
洛谷 题意: 题意好绕好绕...不想写了. 思路: 首先类似于分数规划做法,二分答案得到到每个点的最小危险度. 然后就是在一个二分图中,两边撤掉最少的点(相应代价为上面算出的危险度)及相应边,使得中间 ...
- 洛谷2494 [SDOI2011]保密 (分数规划+最小割)
自闭一早上 分数规划竟然还能被卡精度 首先假设我们已经知道了到每个出入口的时间(代价) 那我们应该怎么算最小的和呢? 一个比较巧妙的想法是,由于题目规定的是二分图. 我们不妨通过最小割的形式. 表示这 ...
- bzoj 1312: Hard Life 01分数规划+网络流
题目: Description 在一家公司中,人事部经理与业务部经理不和.一次,总经理要求人事部从公司的职员中挑选出一些来帮助业务部经理完成一项任务.人事部经理发现,在公司的所有职员中,有一些人相处得 ...
- [转]01分数规划算法 ACM 二分 Dinkelbach 最优比率生成树 最优比率环
01分数规划 前置技能 二分思想最短路算法一些数学脑细胞? 问题模型1 基本01分数规划问题 给定nn个二元组(valuei,costi)(valuei,costi),valueivaluei是选择此 ...
- bzoj 4501: 旅行 01分数规划+概率期望dp
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=4501 题解: 首先我们不考虑可以删除边的情况下,如何计算期望边数. 然后我们发现这是个有 ...
- POJ3621Sightseeing Cows[01分数规划 spfa(dfs)负环 ]
Sightseeing Cows Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9703 Accepted: 3299 ...
- ZOJ 2676 Network Wars ★(最小割算法介绍 && 01分数规划)
[题意]给出一个带权无向图,求割集,且割集的平均边权最小. [分析] 先尝试着用更一般的形式重新叙述本问题.设向量w表示边的权值,令向量c=(1, 1, 1, --, 1)表示选边的代价,于是原问题等 ...
- POJ 2728 Desert King ★(01分数规划介绍 && 应用の最优比率生成树)
[题意]每条路径有一个 cost 和 dist,求图中 sigma(cost) / sigma(dist) 最小的生成树. 标准的最优比率生成树,楼教主当年开场随手1YES然后把别人带错方向的题Orz ...
随机推荐
- 二、antd pro 删除eslint检测
删除package.json 里 " pre-commit": "npm run lint-staged" 这个对象就可以.
- SQL Server数据库字段类型说明
SQL Server数据库字段类型说明 目前Sql Server 数据库一共有X个字段类型,大体分为9类,分别是字符串类型.二进制码字符串数据类型.Unincode字符串数据.整数类型.精确数据类型. ...
- iBatis自动生成工具Abator
https://blog.csdn.net/k_scott/article/details/8281837 ###首先创建数据库表,然后根据数据库表,生成相应的实体.及其配置文件 https://ww ...
- 【上下界网络流 二分】bzoj2406: 矩阵
感觉考试碰到上下界网络流也还是写不来啊 Description Input 第一行两个数n.m,表示矩阵的大小. 接下来n行,每行m列,描述矩阵A. 最后一行两个数L,R. Output 第一行,输出 ...
- python 爬取知乎图片
先上完整代码 import requests import time import datetime import os import json import uuid from pyquery im ...
- GoogleTest 之路3-Mocking Framework
当你写一个原型或者测试的时候,依赖整个object 是不可行和明智的.一个 mock object和 real object 有同样的接口(所以它可以像同一个使用),但是让你在运行时进行指定它应该如何 ...
- 使用GD库做图片水印
png图片作为水印加到其他类型图片后,背景变黑色 原因: imagecopy函数拷贝时可以保留png图像的原透明信息,而imagecopymerge却不支持图片的本身的透明拷贝. 然后直接上代码: / ...
- Python全栈之jQuery笔记
jQuery runnoob网址: http://www.runoob.com/jquery/jquery-tutorial.html jQuery API手册: http://www.runoob. ...
- 中移物联网onenet入门学习笔记1:资料获取
onenet学习资料.视频.例程汇总:https://open.iot.10086.cn/bbs/thread-977-1-1.html onenet开发文档:https://open.iot.100 ...
- 同一条sql在mysql5.6和5.7版本遇到的问题。
之前用的是mysql 5.6版本,执行select * from table group by colunm 是可以出结果的, 但是切换的5.7版本,这条sql就报错, Expression #1 o ...