[洛谷P1401]城市

题目大意:有$n(2leqslant nleqslant200)$个城市,$m(1leqslant mleqslant40000)$条无向边,你要找$T(1leqslant Tleqslant200)$条从城市$1$到城市$n$的路,使得最长的边的长度最小,边不能重复用。

题解:二分答案,跑网络流,每条边边权为$1$,看最大流是否比$T$大。(实测我常数不能再大的$HLPP$跑的比$ISAP$慢,所以就放$ISAP$了,其实都是板子

卡点:

C++ Code:

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#define maxn 210
#define maxm 40010
const int inf = 0x3f3f3f3f;
inline int min(int a, int b) {return a < b ? a : b;}
inline int max(int a, int b) {return a > b ? a : b;}
namespace Network_Flow {
	int st, ed, MF, n;
	int head[maxn], cnt = 2;
	struct Edge {
		int to, nxt, w;
	} e[maxm << 1];
	inline void addE(int a, int b, int c) {
		e[cnt] = (Edge) {b, head[a], c}; head[a] = cnt;
		e[cnt ^ 1] = (Edge) {a, head[b], c}; head[b] = cnt ^ 1;
		cnt += 2;
	}
	int GAP[maxn], d[maxn];
	int last[maxn];
	int q[maxn], h, t;
	inline void init() {
		GAP[d[ed] = 1] = 1;
		for (int i = 1; i <= n; i++) last[i] = head[i]; 
		q[h = t = 0] = ed;
		while (h <= t) {
			int u = q[h++];
			for (int i = head[u]; i; i = e[i].nxt) {
				int v = e[i].to;
				if (!d[v]) {
					d[v] = d[u] + 1;
					GAP[d[v]]++;
					q[++t] = v;
				}
			}
		}
	}
	int dfs(int u, int low) {
		if (!low || u == ed) return low;
		int w, res = 0;
		for (int &i = last[u]; i; i = e[i].nxt) {
			int v = e[i].to;
			if (d[u] == d[v] + 1) {
				w = dfs(v, min(low, e[i].w));
				res += w, low -= w;
				e[i].w -= w, e[i ^ 1].w += w;
				if (!low) return res;
			}
		}
		if (!(--GAP[d[u]])) d[st] = n + 1;
		++GAP[++d[u]], last[u] = head[u];
		return res;
	}
	inline void ISAP(int S, int T) {
		st = S, ed = T;
		init();
		while (d[st] <= n) MF += dfs(st, inf);
	}
	inline void clear() {
		memset(head, 0, sizeof head); cnt = 2;
		memset(GAP, 0, sizeof GAP);
		memset(d, 0, sizeof d);
		MF = 0;
	}
}
#define read() R::READ()
#include <cctype>
namespace R {
	int x;
	#ifdef ONLINE_JUGER
	#define M 1 << 25
	char op[M], *ch;
	inline void init() {fread(ch = op, 1, M, stdin);}
	inline int READ() {
		while (isspace(*ch)) ch++;
		for (x = *ch & 15, ch++; isdigit(*ch); ch++) x = x * 10 + (*ch & 15);
		return x;
	}
	#undef M
	#else
	char ch;
	inline int READ() {
		ch = getchar();
		while (isspace(ch)) ch = getchar();
		for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15);
		return x;
	}
	#endif
}
int n, m, T, M;
int u[maxm], v[maxm], w[maxm];
inline bool check(int mid) {
	for (int i = 1; i <= m; i++) if (w[i] <= mid) Network_Flow::addE(u[i], v[i], 1);
	Network_Flow::ISAP(1, n);
	if (Network_Flow::MF >= T) return true;
	return false;
}
int main() {
	#ifdef ONLINE_JUGER
	R::init();
	#endif
	n = read(), m = read(), T = read();
	Network_Flow::n = n;
	for (int i = 1; i <= m; i++) {
		u[i] = read(), v[i] = read(), w[i] = read();
		M = max(M, w[i]);
	}
	int l = 1, r = M, ans = -1;
	while (l <= r) {
		int mid = l + r >> 1;
		if (check(mid)) {
			r = mid - 1;
			ans = mid;
		} else l = mid + 1;
		if (l <= r) Network_Flow::clear();
	}
	printf("%d
", ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/Memory-of-winter/p/9800340.html