%%%%真的好强...看题解我都看了好久才完全明白。放一下参考的博客,谢谢神犇QAQ

1号博客    2号博客(超级赞的啦)

 因为理解的过程太艰辛,所以必须记录一下这道强题:这道题目最难的两个约束就在于:保证一个时间一只老鼠只吃一块奶酪,一个时间一块奶酪只被一只老鼠吃。第一个想法还是相对明显的:二分答案,离散化时间节点(一个节点代表此节点到上一节点之间的时间段)。

 最妙的一处是老鼠的拆点。在我们之前离散出来的时间段中,每一段都维护m个老鼠的速度差值。我也不知道原作者是怎么想到建图方式的,所以无法解释思路的走向过程,只能说明一下建图的方式&为什么这样是对的。举个例子:我们现在有三只老鼠,速度分别是:5, 4, 3, 那么我们就可以认为是有3只速度为3(3 - 0 = 3)的老鼠,1只速度为1(4 - 3 = 1)的老鼠,还有一只速度为1(5 - 4 = 1)的老鼠。(为什么后面这两只不一样在后面会解释)。暂且将几只记为id,速度记为v。

 s-->每一块奶酪,流量为p[i]; 每一块奶酪-->这个时间段内的老鼠拆点,流量为老鼠拆点v*t(时间); 每一个老鼠拆点-->t,流量为id*v*t。现在让我们来看一下这张图是如何完美的满足了此题的1、2两条约束的:1.保证一个时间一只老鼠只吃一块奶酪:老鼠是按时间段拆的点,连向t,前面所说的拆为了3,1,1的情况,三条都流满说明三只老鼠都在吃,分别流量为1表明速度为3的老鼠在吃...这一点应该还是能够理解的,因为一一对应拆点,必然满足约束。2.保证一个时间一块奶酪只被一只老鼠吃:每一块奶酪都向不同的时间段的拆点通了流量,注意这里的流量并没有乘上id,所以都等于1*v*t,也就满足了一只老鼠的约束。

  以下是代码:(没有看懂的只要手抄一次代码,想必就能明白啦!)

#include <bits/stdc++.h>
using namespace std;
#define maxn 100000
#define eps 0.0000001
#define INF 99999999.00
#define db double
int n, m, s, t, cnp, head[maxn], lev[maxn], cur[maxn];
db R, L, tot, p[maxn], r[maxn], d[maxn], T[maxn], v[maxn];
struct edge
{
int to, last;
db c;
}E[maxn]; bool cmp(db a, db b)
{
return a > b;
} void add(int u, int v, db c)
{
E[cnp].to = v, E[cnp].last = head[u], E[cnp].c = c; head[u] = cnp ++;
E[cnp].to = u, E[cnp].last = head[v], E[cnp].c = ; head[v] = cnp ++;
} bool bfs()
{
queue <int> q;
memset(lev, , sizeof(lev));
q.push(s); lev[s] = ;
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i = head[u]; i != -; i = E[i].last)
{
int v = E[i].to;
if(!lev[v] && E[i].c > eps)
{
lev[v] = lev[u] + ;
if(lev[t]) return true;
q.push(v);
}
}
}
return false;
} db dfs(int u, db nf)
{
if(u == t || nf < eps) return nf;
bool done = false;
db ff = 0.0;
for(int i = cur[u]; i != -; i = E[i].last)
{
int v = E[i].to;
if(!nf) break;
if(E[i].c > eps && lev[v] == lev[u] + )
{
done = true;
db af = dfs(v, min(E[i].c, nf));
cur[u] = i;
nf -= af, ff += af;
E[i].c -= af, E[i ^ ].c += af;
}
}
if(!done) lev[u] = -;
return ff;
} db dinic()
{
db flow = 0.0;
while(bfs())
{
memcpy(cur, head, sizeof(head));
flow += dfs(s, INF);
}
return flow;
} void init()
{
cnp = ;
memset(head, -, sizeof(head));
} void solve()
{
db sum = tot; s = , t = * m * n + n + ;
int cnt = ;
while(R - L > eps)
{
db mid = (R + L) / 2.0;
init();
for(int i = ; i <= n; i ++)
{
add(, i, p[i]);
T[ * i - ] = r[i], T[ * i] = d[i] + mid;
}
sort(T + , T + * n + ), cnt = n;
for(int i = ; i <= m; i ++)
{
for(int j = ; j <= * n; j ++)
{
if(T[j] - T[j - ] < eps) continue;
++ cnt; add(cnt, t, i * v[i] * (T[j] - T[j - ]));
for(int k = ; k <= n; k ++)
{
if(r[k] - T[j - ] < eps && (d[k] + mid - T[j] > -eps))
add(k, cnt, v[i] * (T[j] - T[j - ]));
}
}
}
db maxflow = dinic();
if(sum - maxflow < eps) R = mid;
else L = mid;
}
printf("%lf\n", L);
} int main()
{
int T;
scanf("%d", &T);
while(T --)
{
tot = 0.0;
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i ++)
{
scanf("%lf%lf%lf", &p[i], &r[i], &d[i]);
tot += p[i];
}
for(int i = ; i <= m; i ++) scanf("%lf", &v[i]);
sort(v + , v + + m, cmp);
R = (db) tot / v[] + 1.0, L = 0.0;
for(int i = ; i < m; i ++) v[i] -= v[i + ];
solve();
}
return ;
}

【题解】ZJOI2010贪吃的老鼠的更多相关文章

  1. Luogu2570 [ZJOI2010]贪吃的老鼠 ---- 网络流

    Luogu2570  [ZJOI2010]贪吃的老鼠 题面描述 https://www.luogu.org/problemnew/show/P2570 然后题意大概就是m只老鼠,然后吃n个奶酪,已知 ...

  2. Luogu P2570 [ZJOI2010]贪吃的老鼠

    Luogu P2570 [ZJOI2010]贪吃的老鼠 题目描述 奶酪店里最近出现了\(m\)只老鼠!它们的目标就是把生产出来的所有奶酪都吃掉.奶酪店中一天会生产\(n\)块奶酪,其中第\(i\)块的 ...

  3. [ZJOI2010]贪吃的老鼠(网络流+建图)

    题目描述 奶酪店里最近出现了m只老鼠!它们的目标就是把生产出来的所有奶酪都吃掉.奶酪店中一天会生产n块奶酪,其中第i块的大小为pi,会在第ri秒被生产出来,并且必须在第di秒之前将它吃掉.第j只老鼠吃 ...

  4. [ZJOI2010]贪吃的老鼠 网络流

    ---题面--- 题解: 这是一道强题emmmm,做法非常巧妙,,,我也是看了好久大佬题解才看明白一点 首先考虑没有限制的情况,即n个老鼠可以在同一时刻吃同一块奶酪 对各个时间段拆点,连奶酪 ---& ...

  5. P2570 [ZJOI2010]贪吃的老鼠

    传送门 →_→唯一一篇能看得懂的题解---->这里 很容易想到二分+网络流,然而并没有什么卵用--出题人的思路太神了-- 首先考虑如果一块奶酪在同一时间可以被多只老鼠吃的话,该如何建图.首先不难 ...

  6. [ZJOI2010]贪吃的老鼠

    很不错的一道网络流的题目 二分答案是显然的 首先不考虑每个饼干只能一个老鼠吃 那很显然的建图就是将时间点按照开始结束的点分成2*n-1段 然后对每一段时间建m个老鼠的点,然后s-它限流,再从它到目前可 ...

  7. Luogu2570 ZJOI2010 贪吃的老鼠 二分答案+最大流

    题目链接:https://www.luogu.org/problemnew/show/P2570 题意概述: 好像没什么好概述的.....很简洁? 分析: 首先想到二分时间,转化成判定性问题,在一定时 ...

  8. luogu P2570 [ZJOI2010]贪吃的老鼠【二分+最大流】

    首先考虑只满足第一个条件,二分答案,把过期时间加上mid之后的2n个时间离散,老鼠拆成每个时间的,第i个时间第j个老鼠为id[i][j],连接(s,i,p[i]),对于离散后时间(g[j-1]~g[j ...

  9. 洛谷$P2570\ [ZJOI2010]$贪吃的老鼠 网络流+二分

    正解:网络流+二分 解题报告: 传送门$QwQ$ 和上一题有点儿像,,,?$QwQ$但是比上一题要有趣很多$QwQ$ 首先把大致思路捋下?依然是.二分出每个奶酪的开始和结束时间,然后check下最大流 ...

随机推荐

  1. 常用 css html 样式

    CSS基础必学列表 CSS width宽度 CSS height高度 CSS border边框 CSS background背景 CSS sprites背景拼合 CSS float浮动 CSS mar ...

  2. 【ajax】ajax异步实现用户注册验证

    从前台到后台实现简单用户注册检查用户是否存在 1.编写domain public class User { private String username; private String passwo ...

  3. Python3 列表,元组,字典,字符串知识小结

    一.知识概要 1. 列表,元组,字典,字符串的创建方式 2. 列表,元组,字典,字符串的方法调用 3. 列表,元组,字典,字符串的常规用法 二.列表 # 列 表 # 列表基础 list_1 = ['a ...

  4. R语言学习笔记(十一):零碎知识点(26-30)

    26--aggregate( ) 函数aggregate()对分组中的每一个变量调用tapply()函数. aggregate(a,list,f) 第二个参数必须是列表.也就是因子部分. 第三个参数即 ...

  5. 【Java】关于Spring MVC框架的总结

    SpringMVC是一种基于Java,实现了Web MVC设计模式,请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦.基于请求驱动指的就是使用请求-响应模型,框架的 ...

  6. 关于PHP性能提升踩过的一些坑

        性能这个东西,在网站规模到达一定程度后,会是一个永恒的主题.关于这方面,本人有一些拙见,现在拿出来,大家一起探讨下.     1.编码过程中,传递参数时,尽量少使用‘引用传参’.这是一个巨坑啊 ...

  7. Hue 工具使用

    Hue 是一个 Web 接口的 Hadoop 分析数据工具,由 Cloudra 公司开源 官方网址 Github 地址 -> 安装方法 文档地址 一.Build 1.ubuntu安装所需环境(以 ...

  8. 将List中的数据更新到数据库中

    List中有相应的数据,更新到数据库如下: 1.根据关键字查找后删除: foreach (var item in objSelList) { ADDaAn da = db.ADDaAns.Find(i ...

  9. Mysql数据库的压力

    rationalError: (2006, 'MySQL server has gone away') 2017年10月10日 20:04:43 阅读数:377 问题描述 使用django+celer ...

  10. PADS9.5的常用菜单栏

    1. PAD9.5常用的2个菜单是布线工具和选择过滤工具. 2. 布线工具菜单,如下图,依次是选择,移动,复制,删除,添加元件,布线,新建层次化符号,交换参考编号,交换引脚,添加总线,分割总线,延伸总 ...