~~~题面~~~

题解:

这是一道强题emmmm,做法非常巧妙,,,我也是看了好久大佬题解才看明白一点

首先考虑没有限制的情况,即n个老鼠可以在同一时刻吃同一块奶酪

对各个时间段拆点,连奶酪 ---> 老鼠(反过来也是一样的,只不过不方便),相连的奶酪要符合时间段的限制,

相当于把老鼠拆成很多个小时刻,连向这个时刻它可以吃的奶酪,流量为它在这段时间内可以吃的奶酪总量,

限流可以在汇点到老鼠的路径上进行。

但这个并不能满足同一时刻一块奶酪只能被一个老鼠吃这个条件,因此我们对老鼠再拆点,

把每个老鼠拆成的小时刻再根据速度差分,

比如8 4 2 1,四只老鼠。差分后就是:

8 - 4 = 4;

4 - 2 = 2;

2 - 1 = 1;

1 - 1 = 1;

然后按照编号来定权值

流量就为编号 * 速度(差分后) * 时间;

为什么这样?

8 = 4 + 2 + 1 + 1

4 = 2 + 1 + 1

2 = 1 + 1

1 = 1

可以很明显看到这是一个三角形,且每层都是相同的数字,对应到我们差分数组,对于每个差分后的速度,刚好有编号个,

这样就可以保证总的流量合法了。

那为什么这样可以保证同一时刻只有一只老鼠呢?

可以这样感性的理解:

注意到任意一只老鼠都可以由差分数组凑出,那么不管网络流怎样跑出答案,我们都可以通过分解一下流量,加加减减之类的数学方法凑成这几只老鼠,因此是合法的。

也就是说网络流跑出的东西也许跟原图不一样,但它可以用来判断是否合法(满流即合法),这就够了。

因此我们二分答案,每次都重新建图,跑最大流,满流为true,else 为 false。

代码有点长(打的isap),改成dinic应该会短很多

(数组开这么小是卡常后的结果,,,,)

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 5000
#define ac 20000
#define eps 1e-6
int x, n, m, T, cnt, tmp, ss, tt;
int p[AC], v[AC], last[AC];
double all, ll, rr, mid, ans, addflow;
double r[AC], d[AC], haveflow[ac], t[AC];
int Head[AC], Next[ac], date[ac], tot;
int good[AC], have[AC], c[AC];
int q[AC], tail, head;
/*神奇的网络流,,,,
对每个时间点进行离散化*/
inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} inline void upmin(double &a, double b)
{
if(b < a) a = b;
} inline void add(int f, int w, double S)
{
date[++tot] = w, Next[tot] = Head[f], haveflow[tot] = S, Head[f] = tot;
date[++tot] = f, Next[tot] = Head[w], Head[w] = tot;
//printf("%d ---> %d %.4lf\n",f,w,S);
} bool bfs()
{
int x, now;
head = tail = ;
c[tt] = , have[] = , q[++tail] = tt;
while(head < tail)
{
x = q[++head];
for(R i = Head[x]; i ; i = Next[i])
{
now = date[i];
if(haveflow[i ^ ] && !c[now])
{
c[now] = c[x] + ;
q[++tail] = now;
++have[c[now]];
}
}
}
memcpy(good, Head, sizeof(Head));
return c[ss];
} void aru()
{
while(x != ss)
{
haveflow[last[x]] -= addflow;
haveflow[last[x] ^ ] += addflow;
x = date[last[x] ^ ];
}
ans += addflow;
} double isap()
{
int now; bool done;
x = ss, addflow = INT_MAX;
while(c[ss] != ac + )
{
if(x == tt) aru(), addflow = INT_MAX;
done=false;
for(R i = good[x]; i ; i = Next[i])
{
now = date[i];
if(c[now] == c[x] - && haveflow[i])
{
last[now] = i;
upmin(addflow, haveflow[i]);
good[x] = i;
done = true;
x = now;
}
}
if(!done)
{
int go = ac;
for(R i = Head[x]; i ; i = Next[i])
{
now = date[i];
if(haveflow[i] && c[now]) go = c[now];
}
if(!(--have[c[x]])) break;
++have[c[x] = go + ];
good[x] = Head[x];
if(x != ss) x = date[last[x] ^ ];//这是回到上一个节点啊
}
}
return ans;
} inline bool cmp(double a, double b)
{
return a > b;
} void pre()
{
tot = , all = ;
n = read() ,m = read();
for(R i = ; i <= n; i++)
{
p[i] = read(), r[i] = read(), d[i] = read();
all += (double)p[i];
}
for(R i = ; i <= m; i++) v[i] = read();
sort(v + , v + m + , cmp);//error!!!老鼠是m只!!!!不是n只!!!
rr = (double) all / (double)v[] + 1.0, ll = ;
for(R i = ; i < m; i++) v[i] -= v[i + ];//对速度差分
} void build()
{
tot = , ans = ;
memset(Head, , sizeof(Head));//应该要放这里重置吧
memset(have, , sizeof(have));
memset(c, , sizeof(c));
for(R i = ; i <= n; i++)
{
add(ss, i, p[i]);
t[ * i - ] = r[i], t[ * i] = d[i] + mid;//为离散化做准备
}
sort(t + , t + * n + );//准备离散化了
cnt = , tmp = n;//因为不能和前n个奶酪的编号重了
int a = * n;
t[a + ] = INT_MAX;//不然最后一个点进不来
for(R i = ; i <= a; i++)
if(t[i + ] - t[i] > eps) t[++cnt] = t[i];//去重
for(R i = ; i <= m; i++)//枚举老鼠
{
for(R j = ; j <= cnt; j++)//因为要两个时间点才组成一个时间段
{
++tmp;
add(tmp, tt, i * v[i] * (t[j] - t[j - ]));//连离散化的老鼠到汇点
for(R k = ; k <= n; k++)//枚举奶酪
{
if(r[k] - t[j-] < eps && (d[k] + mid - t[j] > - eps))
add(k, tmp, v[i] * (t[j] - t[j - ]));//连奶酪向老鼠
}//r可以小于t(早就开始了),所以负数也合法,后面是同理的,只是移项了tarjan123 }
}
} void half()
{
ss = * m * n + n + , tt = ss + ;//error!!!ss是要2 * m * n + n + 1啊
while(rr - ll > eps)
{
mid = (rr + ll) / 2.0;
build();
if(bfs() && all - isap() < eps) rr = mid;
else ll = mid;
//printf("%.4lf\n",ans);
//printf("%.4lf %.4lf\n\n",ll,rr);
}
printf("%lf\n", ll);
} void work()
{
T=read();
while(T--)
{
pre();
half();
} } int main()
{
// freopen("in.in","r",stdin);
//freopen("cheese.out","w",stdout);
work();
// fclose(stdin);
//fclose(stdout);
return ;
}

[ZJOI2010]贪吃的老鼠 网络流的更多相关文章

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

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

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

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

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

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

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

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

  5. [ZJOI2010]贪吃的老鼠

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

  6. P2570 [ZJOI2010]贪吃的老鼠

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

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

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

  8. 【题解】ZJOI2010贪吃的老鼠

    %%%%真的好强...看题解我都看了好久才完全明白.放一下参考的博客,谢谢神犇QAQ 1号博客    2号博客(超级赞的啦) 因为理解的过程太艰辛,所以必须记录一下这道强题:这道题目最难的两个约束就在 ...

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

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

随机推荐

  1. JQuery表单验证插件

    使用jQuery的validate插件实现一个简单的表单验证 <!DOCTYPE html> <html> <head> <meta charset=&quo ...

  2. angualarjs $location服务

    $location服务 angular使用内置的$location服务来监听.操作url,包括以下功能: - 获取.监听.改变地址栏的URL: - 与URL实现双向数据绑定(地址栏变动.前进后退或者点 ...

  3. unable to access android sdk add-on list and SDK 更新镜像设置

    前记 国内的网络呀,真是操蛋!!!!!! unable to access android sdk add-on list 在 Android Studio 安装目录 bin/idea.propert ...

  4. 洪水!(Flooded! ACM/ICPC World Final 1999,UVa815)

    题目描述:竞赛入门经典的习题4-10 解题思路:1.把各个网格想象成一个数组 2.排序 3.雨水总体积去铺满 //太懒了只写了求海拔 #include <stdio.h> #define ...

  5. 小程序解析html和富文本编辑内容【亲测有效】

    首先去 https://github.com/icindy/wxParse 下载wxParse,只拷贝wxParse文件夹即可. 1.引入wxss @import "../../util/w ...

  6. python作业:三级菜单(第一周)

    一.作业需求: 1. 运行程序输出第一级菜单 2. 选择一级菜单某项,输出二级菜单,同理输出三级菜单 3. 菜单数据保存在文件中 4. 让用户选择是否要退出 5. 有返回上一级菜单的功能 二.三级菜单 ...

  7. 有关WCSF的几点整理

    本文示例代码 一.CreateNew Attribute实现属性注入 Steps: 1/ aspx创建某个服务的属性. 2/ 为其添加[CreateNew] Attribute. 3/ 页面继承自Mi ...

  8. linux 文件已经删除,但是空间没有释放的原因

    监控系统报告一台服务器的空间满了,登陆后发现/tmp下有大量access_log文件,分析是Apache的日志文件很久没有清理了,确认并执行删除操作. 但是,问题来了,执行 rm /tmp/acces ...

  9. POJ 1815 Friendship(最大流最小割の字典序割点集)

    Description In modern society, each person has his own friends. Since all the people are very busy, ...

  10. HDU 4169 Wealthy Family(树形DP)

    Problem Description While studying the history of royal families, you want to know how wealthy each ...