1 条题解
-
0
自动搬运
来自洛谷,原作者为

岸芷汀兰
岸芷汀兰,郁郁青青。搬运于
2025-08-24 22:25:19,当前版本为作者最后更新于2021-07-05 10:23:48,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
一、题目:
二、思路:
这道题整整让我调了一个下午!一直被精度卡,后来把所有的精度全部取消就 A 了!
现在让我们来系统梳理一下这道题的思路。
首先可以看出,题目中的参数 纯粹是迷惑人的。我们完全可以将 看成一个新流。最终求出来答案再除以 即可。
我们试想这样一种情况:新建一个超级源点 ,从 分别向 1、2 号点连容量是无穷大的边,设从 向 3 号点跑最大流得到的答案是 。那么一定有 。
最终的答案设成一个函数 ,对该函数求导,得
$$\begin{aligned} f'(F)&=aF^{a-1}(Z-F)^{1-a}-F^a(1-a)(Z-F)^{-a}\\ &=F^a(Z-F)^{-a}\left(\dfrac{a(Z-F)}{F}-1+a\right)\\ &=F^a(Z-F)^{-a}\dfrac{aZ-F}{F} \end{aligned} $$则当 时,;当 时,。所以当 时, 有极大值。
但是接下来有两个问题亟待我们去解决。
第一个问题是我们可能无法让 达到 。设从 1 号点向 3 号点跑最大流的答案是 ,从 2 号点向 3 号点跑最大流的答案是 。那么, 的范围(或者可以理解为定义域)为 。所以我们只需要在 的定义域找见距离 最近的值即可。设该值为 ,。
第二个问题是,有可能 所对应的流和 所对应的流叠加在一起时,会造成同一根水管会有不同方向的两条流。但是,我们可以构造出一种满足题意的流。
- 从 向 1 号点连容量为 的边,向 2 号点连容量是 的边。再从 向 3 号点跑最大流。
- 新建一张图 ,新图边的方向为旧图中最大流的流向,容量为旧图中最大流的流量。
- 从新图的超级源点 向 1 号点连容量为 的边,再从 向 3 号点跑最大流。此时每条边的流量就是 Flubber 的最终答案,每条边的容量减流量就是 water 的最终答案。
显然,由于新图的每条边的流量守恒,容量也守恒,所以 water 的流量也是守恒的。而且 Flubber 的流量一定是 ,water 的流量一定是 。
三、代码:
#include <iostream> // 不要设任何的eps! #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define FILEIN(s) freopen(s, "r", stdin) #define FILEOUT(s) freopen(s, "w", stdout) #define mem(s, v) memset(s, v, sizeof s) inline int read(void) { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return f * x; } const int MAXN = 205, MAXM = MAXN * MAXN; const double INF = 1e9; int n, m, head[MAXN], tot = 1, S, T; int q[MAXN], cur[MAXN], d[MAXN]; int dir[MAXM]; double Fmax, Wmax, Z, F$, W$, ans, v, a; struct Edge { int y, next; double w; Edge() {} Edge(int _y, int _next, double _w) : y(_y), next(_next), w(_w) {} }e[MAXM]; inline void add(int x, int y, double w) { e[++ tot] = Edge(y, head[x], w); head[x] = tot; } inline void connect(int x, int y, double w) { add(x, y, w); add(y, x, w); } bool bfs(void) { int hh = 0, tt = -1; q[++ tt] = S; cur[S] = head[S]; mem(d, -1); d[S] = 0; while (hh <= tt) { int x = q[hh ++]; for (int i = head[x]; i; i = e[i].next) { int y = e[i].y; if (e[i].w > 0 && d[y] == -1) { d[y] = d[x] + 1; cur[y] = head[y]; if (y == T) return true; q[++ tt] = y; } } } return false; } double find(int x, double limit) { if (x == T) return limit; double flow = 0; for (int i = cur[x]; i && flow < limit; i = e[i].next) { cur[x] = i; int y = e[i].y; if (e[i].w > 0 && d[y] == d[x] + 1) { double t = find(y, min(e[i].w, limit - flow)); if (t == 0) d[y] = -1; e[i].w -= t; e[i ^ 1].w += t; flow += t; } } return flow; } double dinic(void) { double r = 0, flow; while (bfs()) { if ((flow = find(S, INF)) > 0) r += flow; } return r; } inline void restore(void) { for (int i = 2; i <= tot; i += 2) { double mid = (e[i].w + e[i ^ 1].w) / 2.0; e[i].w = e[i ^ 1].w = mid; } } int main() { n = read(); m = read(); scanf("%lf%lf", &v, &a); for (int i = 1; i <= m; ++ i) { int x = read(), y = read(); double w; scanf("%lf", &w); connect(x, y, w); } S = 1; T = 3; Fmax = dinic(); restore(); S = 2; Wmax = dinic(); restore(); S = n + 1; connect(S, 1, INF); connect(S, 2, INF); Z = dinic(); restore(); if (Z - Wmax > a * Z) F$ = Z - Wmax; else if (Fmax < a * Z) F$ = Fmax; else F$ = a * Z; W$ = Z - F$; ans = pow(F$, a) * pow(W$, 1 - a); ans /= pow(v, a); for (int i = head[n + 1]; i; i = e[i].next) { int y = e[i].y; if (y == 1) e[i].w = F$, e[i ^ 1].w = 0; else e[i].w = W$, e[i ^ 1].w = 0; } dinic(); for (int i = 2; i <= tot; i += 2) { double mid = (e[i].w + e[i ^ 1].w) / 2; if (e[i ^ 1].w > mid) { dir[i] = 1; e[i].w = e[i ^ 1].w - mid; e[i ^ 1].w = 0; } else { dir[i] = -1; e[i ^ 1].w = e[i].w - mid; e[i].w = 0; } } for (int i = head[n + 1]; i; i = e[i].next) { int y = e[i].y; if (y == 1) { e[i].w = F$; e[i ^ 1].w = 0; } else e[i].w = e[i ^ 1].w = 0; } S = n + 1; dinic(); tot -= 4; for (int i = 2; i <= tot; i += 2) { if (dir[i] == 1) printf("%.8lf %.8lf\n", e[i ^ 1].w / v, e[i].w); else printf("-%.8lf -%.8lf\n", e[i].w / v, e[i ^ 1].w); } printf("%.8lf\n", ans); return 0; }
- 1
信息
- ID
- 6086
- 时间
- 4500ms
- 内存
- 512MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者