%%%%真的好强...看题解我都看了好久才完全明白。放一下参考的博客,谢谢神犇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. Discuz论坛搜索下拉框插件openSug

    Discuz!只需安装openSug插件即可获得带有“搜索框提示”功能的搜索框,让您的Discuz搜索更便捷! 下载:https://www.opensug.org/faq/.../opensug.d ...

  2. laravel -- 路由

    基本路由 Route::get('/get',function (){ return "this is get"; }); Route::post('/post',function ...

  3. Excel VBA表格自行开发计划

    Excel VBA表格自行开发计划 要求功能 1. 批量删除 2. [X] 批量填充 3. [X] 批量重命名 4. [ ] 按颜色求和 5. [ ] 按底纹色选中单元格 6. [ ] 统计底纹颜色个 ...

  4. zabbix配置报警媒介-用户-动作-邮件脚本触发mailx邮件报警

    2018-09-16更新,新版本zabbix不需要使用脚本发送邮件,在zabbix web界面直接配置就可以 配置邮件参数,测试发送邮件 确认安装相关服务,centos7默认安装 [root@VM_1 ...

  5. linux文件操作篇 (一)文件属性与权限

    文件的属性和权限是linux中 目录 和 文件 的两个基本特性. #属性: . 所有者属性 . 访问权限属性   -rwxrwxr-x #第一个字符是文件类别 -表示 普通文件 d 表示目录 b 表示 ...

  6. 创建react

    cnpm install -g create-react-app 安装项目create-recat-app myapp

  7. Virtual Host on Apache(Apache上建立虚拟主机)

    0. Introduction Usually, we want to build two or more websites on a web server, but we have only one ...

  8. MediaTypeListWidget->insertItem 添加的label没有填充单元格

    label没有填充满当前的item,但是主界面拉伸或者大小变化之后会填充当前的item 类似相关的问题我猜测都是因为子控件或者需要参考的控件的参考对象的大小在初始化的时候还没有完成最终的初始化,导致大 ...

  9. Android Google Maps 开始

    由于工作需要,最近对Android的各大地图进行了试用. 其中有Google地图,百度地图,高德地图,还有开源的OSM. 在使用Google地图的时候,官网流程写的非常清楚,但是其中也遇到一些问题.这 ...

  10. Sersync实时备份服务部署实践