ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【题解】BZOJ4669 - 抢夺

2022-02-26 19:34:39  阅读:160  来源: 互联网

标签:BZOJ4669 int 题解 ll flow leq edge 抢夺 dis


题意

给出一个包含 \(n\) 个点和 \(m\) 条边的有向图。点的编号为 \(0\) 到 \(n - 1\)。第 \(i\) 条边 \((u_i, v_i)\) 有其同一时刻最多能容纳的人数 \(c_i\) ,且通过每条边的时间均为 \(1\)。

初始时在源点 \(0\) 有 \(k\) 个人,试求 \(k\) 个人均到达汇点 \(n - 1\) 所需的最小时间。若 \(k = 0\),则认为需要 \(0\) 个时刻。

\(1 \leq n \leq 10^3, 1 \leq m \leq 5 \times 10^3, 0 \leq k \leq 10^9\)

\(\forall (u, v) \in E,\ 0 \leq u, v < n, 1 \leq c_i \leq 10^9\)

多测,数据不超过 \(10\) 组。

思路

费用流 + 二分答案。

一个显然的思路是将每个点拆成不同时刻的若干点,然后在分层图上跑最大流。事实上这个做法可以 AC 此题的弱化版 P4400 [JSOI2008]Blue Mary的旅行,原因是该题的层数上界较小。但是此题的数据范围太大,会 TLE 30 分。

考虑将每条边的通过时间视为费用,最大能容纳的人数视为容量。贪心的想法是每次都走最短路,但是这样做可能导致若干人汇集到一个点上等待,所以可以考虑从最短路开始,每次在当前有人经过的路径集合中替换或加入路径(均为较短路),遍历到所有可行的方案。

显然答案有单调性,不妨考虑用二分答案实现。每次枚举当前的时间上限 \(t\),如果在超过时刻 \(t\) 前可以令 \(k\) 个人都到达点 \(n - 1\),则可以用 \(t\) 更新答案。

假设在残量网络中找到了一条长度为 \(d\),流量为 \(f\) 的增广路。如果这条增广路不含反向边,显然可以令源点每个时刻都出发 \(f\) 个人走该路径到 \(t\),即该路径从时刻 \(d\) 开始,在超过时刻 \(t\) 前共可以运输 \((t - d + 1) \cdot f\) 人。

如果该路径含反向边,相当于将这条路径划分给原本的一条较短路和一条新的较短路。此时将 \((t - d + 1) \cdot f\) 人统计进可以运输的总人数,实际上相当于用该反向边的费用撤销了原本的较短路花费的时间。

如图,假设此前有人经过路径 \(s, 1, 2, t\),则当通过路径 \(s, 2, 1, t\) 增广到反向边 \(2, 1\) 时,相当于原本的较短路 \(s, 1, 2, t\) 替换成两条较短路 \(s, 1, t\) 和 \(s, 2, t\),原本走过 \(1, 2\) 边需要的时间则通过 \(2, 1\) 边撤销。

我们发现上面换最短路的过程和 EK 类似,所以直接用 EK 写即可。时间复杂度为 EK 的复杂度套 \(\log(\textrm{V})\),其中 \(V\) 为答案值域,可以取 \(10^{12}\)

代码

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;

typedef long long ll;

const int maxn = 1e3 + 5;
const int maxm = 1e4 + 5;
const int maxk = 5e3 + 5;
const int inf = 0x3f3f3f3f;
const ll flow_max = 1e18;

struct node {
	int to, nxt, w, c;
} edge[maxm];

int n, m, k, s, t;
int cnt = 1, mc;
int ui[maxk], vi[maxk], wi[maxk];
int head[maxn], dis[maxn], pre[maxn];
ll sum, mf, flow[maxn];
bool in_queue[maxn];

void add_edge(int u, int v, int w, int c) {
	cnt++;
	edge[cnt].to = v;
	edge[cnt].nxt = head[u];
	edge[cnt].w = w;
	edge[cnt].c = c;
	head[u] = cnt;
}

void add(int u, int v, int w, int c) {
	add_edge(u, v, w, c);
	add_edge(v, u, 0, -c);
}

bool spfa() {
	queue<int> q;
	memset(dis, 0x3f, (t + 1) * sizeof(int));
	dis[s] = 0;
	flow[s] = flow_max;
	in_queue[s] = true;
	q.push(s);
	while (!q.empty()) {
		int u = q.front();
		q.pop();
		in_queue[u] = false;
		for (int i = head[u]; i; i = edge[i].nxt) {
			int v = edge[i].to;
			if ((dis[v] > dis[u] + edge[i].c) && edge[i].w) {
				dis[v] = dis[u] + edge[i].c;
				flow[v] = min(flow[u], 1ll * edge[i].w);
				pre[v] = i;
				if (!in_queue[v]) {
					in_queue[v] = true;
					q.push(v);
				}
			}
		}
	}
	return (dis[t] < inf);
}

void edmonds_karp(ll mid) {
	while (spfa()) {
		int cur = t;
		mf += flow[t];
		while (cur != s) {
			edge[pre[cur]].w -= flow[t];
			edge[pre[cur] ^ 1].w += flow[t];
			cur = edge[pre[cur] ^ 1].to;
		}
		sum += max(0ll, 1ll * (mid - dis[t] + 1ll) * flow[t]);
	}
}

bool check(ll mid) {
	cnt = 1;
	mc = mf = sum = 0;
	memset(head, 0, (t + 1) * sizeof(int));
	for (int i = 1; i <= m; i++) {
		add(ui[i], vi[i], wi[i], 1);
	}
	edmonds_karp(mid);
	return (sum >= k);
}

ll work() {
	ll l = 1, r = 1e12;
	while (l < r) {
		ll mid = (l + r) >> 1;
		if (check(mid)) {
			r = mid;
		} else {
			l = mid + 1;
		}
	}
	return l;
}

int main() {
	int u, v, w, c;
	while (scanf("%d%d%d", &n, &m, &k) != EOF) {
		s = 1, t = n;
		for (int i = 1; i <= m; i++) {
			scanf("%d%d%d", &ui[i], &vi[i], &wi[i]);
			ui[i]++, vi[i]++;
		}
		if (!k) {
			puts("0");
			continue;
		}
		ll ans = work();
		if (ans != 1e12) {
			printf("%d\n", ans);
		} else {
			puts("No solution");
		}
	}
	return 0;
}

标签:BZOJ4669,int,题解,ll,flow,leq,edge,抢夺,dis
来源: https://www.cnblogs.com/lingspace/p/bzoj4669.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有