Description

题目链接

新年将至,C 校的 \(m\) 位同学们由于在家的生活过于无聊,他们每个人都购买了一个快递。

他们都住在一条街,这条街有\(n\) 个小区,第 \(i\) 个小区 \((1\le i \le n)\) 只与第 \(i+1\) 个小区相连,到第 \(i+1\) 个小区的距离是 \(d_i\) 。第 \(i\) 位同学住在第 \(p_i\) 个小区,这位同学的暴躁程度是 \(d_i\)

你作为快递公司的老板,你想在新年前的最后一天准备干完这 \(m\) 个同学的单子就跑路。快递公司正好有 \(m\) 个邮递员,每个邮递员在最后一天可以将至多一个人的快递(具体是谁的可以由你指定)送去第 \(q_i\) 个小区,然后叫这个人去领快递。

如果一个邮递员在新年的最后一天工作了,他会有 \(c_i\) 的不开心值,而见到同学之后,因为这位同学十分暴躁,又走了一段漫长的路程,他会传递给这个快递员 \(\text{这个同学的暴躁程度}+\text{这位同学所走的路程}\) 的不开心值。而快递员将索要等同于他的不开心值的小费。

迫于压力你只好咕掉某几个同学的快递,想到知道对于所有 \((1\le i \le m)\) 如果发送了 \(m\) 个同学的快递,你最少需要支付多少小费。

\(n \le 800 , m\le 50000\)

Solution

首先可以简单得跑网络流得到 \(30\) 分的成绩。


然后考虑如何把复杂度优化成 \(O(nm)\) 的。

显然无法避免 \(m\) 次增广,所以考虑把一次增广的时间复杂度优化成 \(O(n)\) ,首先考虑一种建图方法:中间的 \(n\) 个点表示 \(n\) 个小区,然后在第 \(i\) 和第 \(i+1\) 号点之间连一条双向边,费用为 \(d_i\) ,流量为 \(\inf\) ,然后对于每一个同学,连一条边 \(s \rightarrow p_i\) ,费用为 \(d_i\) ,流量为 \(1\) ,然后对于每一个快递员,连一条边 \(q_i \rightarrow t\) ,费用为 \(c_i\) ,流量为 \(1\)

显然,对于第 \(i\) 个点,\(s \rightarrow p_i\)\(q_i \rightarrow t\) 只有权值最小的那一条边有用,且一条边没走过后不可能被退流,于是考虑每次只把有用的边放进去跑 spfa 增广

于是我们得到理论复杂度 \(O(knm)\) 的做法,其中 \(k\) 是 spfa 中每个点入队的平均次数, 看上去非常能过,然后你发现你一个大数据跑了 \(5s\) ,然后你看了一下每个点的入次数,发现他没有很大,出题人良心地没有卡 spfa。于是你尝试着卡了一波常,卡到了 \(1.5s\) 之后发现卡不动了。

卡不动的主要原因是,这个做法的常数太大了,我的卡常技术不足以把他卡过去。

考虑一种更优的做法,记录正着走(从 \(i\) 走到 \(i+1\) ),和倒着走的可以退流的次数,然后每次通过正反各扫一遍的方法找到最短路进行增广,以正着扫举例,具体做法是记录最近的能到达当前点的最近的同学,然后和当前点的快递员匹配,每次更新离当前点最近同学的距离。

于是我们得到了一个复杂度是真的 \(O(nm)\) 的做法。

Code

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-17
  • 2021-05-28
  • 2022-01-04
猜你喜欢
  • 2021-10-19
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案