神秘问题
查看原帖
神秘问题
362750
TernaryTree楼主2023/12/5 21:34

处理时使用 solve(0, n) WA40,使用 solve(1, n) AC。

#include <bits/stdc++.h>
#define int long long
#define fs first
#define sc second

using namespace std;

const int maxn = 5e4 + 10;
const int maxd = 21;
const int inf = 1e9;
typedef pair<int, int> pii;

struct edge {
	int to, next;
	int cap, flow;
};

int n, m, s, t, q;
int head[maxn];
edge e[maxn << 1];
int cnt = -1;
vector<pii> tr[maxn];
int d[maxn];
int fa[maxn][maxd];
int mn[maxn][maxd];

void add_edge(int u, int v, int w) {
	e[++cnt].to = v;
	e[cnt].next = head[u];
	e[cnt].cap = w;
	e[cnt].flow = 0;
	head[u] = cnt;
}

void init() {
	for (int i = 0; i <= cnt; i++) e[i].flow = 0;
}

int dep[maxn];
int cur[maxn];

bool bfs() {
	memset(dep, -1, sizeof(dep));
	memcpy(cur, head, sizeof(cur));
	queue<int> q;
	dep[s] = 0;
	q.push(s);
	while (!q.empty()) {
		int u = q.front();
		q.pop();
		for (int i = head[u]; ~i; i = e[i].next) {
			int v = e[i].to;
			if (e[i].flow < e[i].cap && dep[v] == -1) {
				dep[v] = dep[u] + 1;
				q.push(v);
			}
		}
	}
	return dep[t] != -1;
}

int dfs(int u, int fl) {
	if (u == t) return fl;
	int now = fl;
	for (int i = cur[u]; ~i && now > 0; i = e[i].next) {
		cur[u] = i;
		int v = e[i].to;
		if (dep[v] == dep[u] + 1 && e[i].flow < e[i].cap) {
			int tmp = dfs(v, min(now, e[i].cap - e[i].flow));
			e[i].flow += tmp;
			e[i ^ 1].flow -= tmp;
			now -= tmp;
		}
	}
	return fl - now;
}

int ve[maxn];

int dinic() {
	int ans = 0, x;
	while (bfs()) while (x = dfs(s, inf)) ans += x;
	return ans;
}

int qwq[maxn], qaq[maxn], op, qr;

void solve(int l, int r, int de = 0) {
	if (l == r) return;
	init();
	s = ve[l], t = ve[l + 1];
	int w = dinic();
	tr[s].push_back({t, w});
	tr[t].push_back({s, w});
	op = qr = 0;
	for (int i = l; i <= r; i++) {
		if (dep[ve[i]] == -1) qwq[++op] = ve[i];
		else qaq[++qr] = ve[i];
	}
	for (int i = l; i <= r; i++) {
		if (i <= l + op - 1) ve[i] = qwq[i - l + 1];
		else ve[i] = qaq[i - l - op + 1];
	}
	int mid = l + op - 1;
	solve(l, mid, de + 1);
	solve(mid + 1, r, de + 1);
}

void dfs(int u, int f, int wg) {
	mn[u][0] = wg;
	fa[u][0] = f;
	d[u] = d[f] + 1;
	for (int i = 1; i < maxd; i++) {
		fa[u][i] = fa[fa[u][i - 1]][i - 1];
		mn[u][i] = min(mn[u][i - 1], mn[fa[u][i - 1]][i - 1]);
	}
	for (pii v : tr[u]) {
		if (v.fs == f) continue;
		dfs(v.fs, u, v.sc);
	}
}

int lca(int u, int v) {
	int l;
	if (d[u] < d[v]) swap(u, v);
	while ((l = d[u] - d[v]) > 0) u = fa[u][__lg(l)];
	if (u == v) return u;
	for (int d = maxd - 1; ~d; d--) {
		if (fa[u][d] != fa[v][d]) u = fa[u][d], v = fa[v][d];
	}
	return fa[u][0];
}

int getmn(int u, int v) {
	int f = lca(u, v), l, y = inf;
	while ((l = d[u] - d[f]) > 0) {
		y = min(y, mn[u][__lg(l)]);
		u = fa[u][__lg(l)];
	}
	while ((l = d[v] - d[f]) > 0) {
		y = min(y, mn[v][__lg(l)]);
		v = fa[v][__lg(l)];
	}
	return y;
}

signed main() {
	memset(head, -1, sizeof(head));
	cin >> n >> m;
	for (int i = 1, u, v, w; i <= m; i++) {
		cin >> u >> v >> w;
		add_edge(u, v, w);
		add_edge(v, u, 0);
		add_edge(v, u, w);
		add_edge(u, v, 0);
	}
	for (int i = 0; i <= n; i++) ve[i] = i;
	solve(0, n);
	dfs(n, n + 1, inf);
	cin >> q;
	while (q--) {
		int u, v;
		cin >> u >> v;
		cout << getmn(u, v) << endl;
	}
	return 0;
}
2023/12/5 21:34
加载中...