Description

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

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

某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国人之前。

Input

第一行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个出入口。

Output

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

Sample Input

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

Sample Output

17.0

 

【思路】

二分,spfa + 最大流

首先求出从起点到所有出入口的危险性val,题目就是一个最小覆盖的问题,按照奇偶性将节点分作两组,奇数点由S向之连边val,偶数点向T连边val,跑个最大流就好了。

问题是怎么求出危险性。假设答案是ans,如果存在

(t1+t2+…tn)/(s1+s2+…sn)<=ans

      

              t1-ans*s1+t2-ans*s2+…tn-ans*sn<=0

则说明存在更小ans。二分ans,每次跑一遍spfa求出最短路即可。

【代码】

 #include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; const int N = ;
const double INF = 1e12;
const double eps = 1e-;
struct Edge{
int v; double t,s;
Edge(int v,double t,double s) :v(v),t(t),s(s) {}
};
struct Dedge {
int u,v; double cap,flow;
Dedge(int u,int v,double cap,double flow) :u(u),v(v),cap(cap),flow(flow) {}
}; void read(int& x) {
char c=getchar(); int f=; x=;
while(!isdigit(c)) {if(c=='-')f=-; c=getchar();}
while(isdigit(c)) x=x*+c-'',c=getchar();
x*=f;
} struct Dinic {
vector<int> G[N];
vector<Dedge> es;
int n,m,s,t,d[N],cur[N],vis[N];
void init(int n) {
this->n=n;
es.clear();
for(int i=;i<n;i++) G[i].clear();
}
void AddEdge(int u,int v,double w) {
es.push_back(Dedge(u,v,w,));
es.push_back(Dedge(v,u,,));
m=es.size();
G[u].push_back(m-),G[v].push_back(m-);
}
bool bfs() {
int q[N],head=,tail=;
memset(vis,,sizeof(vis));
q[tail++]=s; vis[s]=; d[s]=;
while(head!=tail) {
int u=q[head++];
for(int i=;i<G[u].size();i++) {
Dedge& e=es[G[u][i]];
int v=e.v;
if(!vis[v]&&e.cap>e.flow) {
vis[v]=; d[v]=d[u]+;
q[tail++]=v;
}
}
}
return vis[t];
}
double dfs(int u,double a) {
if(u==t||fabs(a)<eps) return a;
double flow=,f;
for(int& i=cur[u];i<G[u].size();i++) {
Dedge& e=es[G[u][i]];
int v=e.v;
if(d[v]==d[u]+ && (f=dfs(v,min(a,e.cap-e.flow)))>eps) {
e.flow+=f;
es[G[u][i]^].flow-=f;
flow+=f; a-=f;
if(fabs(a)<eps) break;
}
}
return flow;
}
double Maxflow(int s,int t) {
this->s=s,this->t=t;
double flow=;
while(bfs()) {
memset(cur,,sizeof(cur));
flow+=dfs(s,INF);
}
return flow;
}
} dc; vector<Edge> g[N];
int n,m,m1,n1; double val[N];
int head,tail,q[],vis[N]; double dis[N]; //spfa µÄ que bool spfa(int s,int t,double p) {
FOR(i,,n) dis[i]=INF;
memset(vis,,sizeof(vis));
head=tail=; q[tail++]=s;
vis[s]=; dis[s]=;
while(head!=tail) {
int u=q[head++]; vis[u]=;
for(int i=;i<g[u].size();i++) {
int v=g[u][i].v;
if(dis[v]>dis[u]+g[u][i].t-p*g[u][i].s) {
dis[v]=dis[u]+g[u][i].t-p*g[u][i].s;
if(v==t&&dis[v]<eps) return ;
if(!vis[v])
vis[v]= , q[tail++]=v;
}
}
}
return dis[t]<-eps;
} int main() {
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
read(n),read(m);
int u,v,s,t;
FOR(i,,m) {
read(u),read(v),read(t),read(s);
g[u].push_back(Edge(v,(double)t,(double)s));
}
read(m1),read(n1);
FOR(i,,n1) {
double L=,R=,M;
while((double)R-L>1e-) {
M=(L+R)*0.5;
if(spfa(n,i,M)) R=M; else L=M;
}
if(dis[i]==INF) val[i]=INF; else val[i]=(L+R)*0.5;
}
dc.init(n1+);
int S=,T=n1+;
FOR(i,,m1) {
read(u),read(v);
if(v&) swap(u,v);
if(val[u]==INF&&val[v]==INF) {
puts("-1"); return ;
}
dc.AddEdge(u,v,INF);
}
FOR(i,,n1) {
if(i&) dc.AddEdge(S,i,val[i]);
else dc.AddEdge(i,T,val[i]);
}
printf("%.1lf",dc.Maxflow(S,T));
return ;
}

ps:原来我大SD也有如此放(si)荡(xiang)不(wo)羁(chuo)的出题人

spfa的队列要开大一点!spfa的队列要开大一点!spfa的队列要开大一点!

难得一次不用STL,你就wa给我看<_<

bzoj 2285 [Sdoi2011]保密(二分,spfa + 最大流)的更多相关文章

  1. BZOJ 2285 [Sdoi2011]保密

    题解: 求比值用分数规划,单个求太慢了套整体二分 然后求二分图最小割 // luogu-judger-enable-o2 #include<iostream> #include<cs ...

  2. bzoj 1305: [CQOI2009]dance 二分+網絡流判定

    1305: [CQOI2009]dance跳舞 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 1340  Solved: 581[Submit][Sta ...

  3. bzoj 3993 星际战争 - 二分答案 - 最大流

    3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战.在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团的阵地,其中第i个巨型机器人的装甲值为Ai.当一个巨型机器人的装甲值减少到0或者 ...

  4. Bzoj 2282: [Sdoi2011]消防(二分答案)

    2282: [Sdoi2011]消防 Time Limit: 10 Sec Memory Limit: 512 MB Description 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条 ...

  5. bzoj 3130 [Sdoi2013]费用流(二分,最大流)

    Description Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识.    最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量.一个合法的网络 ...

  6. BZOJ 2406 矩阵(二分+有源汇上下界可行流)

    题意 题解 二分答案+可行流判断. 模板题. CODE #include <cstdio> #include <cstring> #include <algorithm& ...

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

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

  8. 【BZOJ2245】[SDOI2011]工作安排(费用流)

    [BZOJ2245][SDOI2011]工作安排(费用流) 题面 BZOJ 洛谷 题解 裸的费用流吧. 不需要拆点,只需要连边就好了,保证了\(W_j<W_{j+1}\). #include&l ...

  9. BZOJ 3876 支线剧情 | 有下界费用流

    BZOJ 3876 支线剧情 | 有下界费用流 题意 这题题面搞得我看了半天没看懂--是这样的,原题中的"剧情"指的是边,"剧情点"指的才是点. 题面翻译过来大 ...

随机推荐

  1. 如何实现一个malloc函数

    一.概述 1.malloc简介 函数所在头文件:<stdlib.h> 函数原型是:void *malloc (size_t n) 函数功能:在内存的动态存储区中分配一个长度为size的连续 ...

  2. JAVA程序性能分析及调优浅析

    1.性能分析本质 寻找系统的性能瓶颈(木桶理论/短板效应),并处理系统的性能瓶颈 2.性能分析主要指标负载.响应和服务器CPU\MEM等的使用率 3.性能分析主要工具 LoadRunner Visua ...

  3. 创建第一个UI

    创建一个2D UI 制作UI时,首先要创建UI的"根".在Unity顶部NGUI菜单中选择Create,然后选择2D UI. 创建完成后,在Scene窗口中,NGUI自动生成了一个 ...

  4. 素数筛&&欧拉筛

    折腾了一晚上很水的数论,整个人都萌萌哒 主要看了欧拉筛和素数筛的O(n)的算法 这个比那个一长串英文名的算法的优势在于没有多次计算一个数,也就是说一个数只筛了一次,主要是在%==0之后跳出实现的,具体 ...

  5. 扩展pl0编译器设计——总述

    所谓编译器,实际上就是我们编程时将输入的高级语言代码转换成相应的目标代码,从而实现将目标代码转换成汇编码的一种过渡工具. 这种工具根据具体情况不同,可以将不同的高级语言代码转换成不同的目标代码,例如将 ...

  6. C3p0的参数设置

    C3p0的参数设置:ComboPooledDataSource和BasicDataSource一样提供了一个用于关闭数据源的close()方法,这样我们就可以保证Spring容器关闭时数据源能够成功释 ...

  7. Linux fdisk 命令

    Linux fdisk 命令 fdisk                         fdisk功能说明:磁盘分区.语 法:fdisk [-b <分区大小>][-uv][外围设备代号] ...

  8. 一些常用的jQuery插件

    1. X-editable 这个插件能够让你在页面上创建可编辑的元素.它能够使用任何引擎(bootstrap.jquery-ui.jquery),并且包含弹出式和内联模式. 2. Garlic.js ...

  9. 云告警平台 OneAlert :如何帮助运维工程师做好汇报?

    OneAlert 是北京蓝海讯通科技有限公司旗下产品,中国首个 SaaS 模式的云告警平台,可集成 Zabbix ,Nagios ,Solarwinds ,AWS CloudWatch ,阿里云 ,监 ...

  10. UVA 10269 Adventure of Super Mario

    看了这里 http://blog.csdn.net/acm_cxlove/article/details/8679230的分析之后自己又按照自己的模板写了一遍,算是对spfa又加深了一步认识(以前真是 ...