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

Alex_Wei
**搬运于
2025-08-24 22:25:06,当前版本为作者最后更新于2022-09-25 08:35:34,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
比较简单的网络流。
拆点限制每个点只能经过一次。 连容量 ,容量下界 ,权值 的边; 连容量 ,权值 的边; 连容量 ,权值 的边。 连容量 ,权值 的边。
我们发现直接流 会出错,因为并不一定需要满流。因此,考虑从 到 枚举最优流量,每次添加 容量 ,权值 的边,将任意时刻最小费用取 即可。时间复杂度是 次有源汇上下界费用流。
避免上下界网络流的方法:我们知道 的流量恰为 且无权,不妨将其权值设为一个绝对值小于两倍边权的负数,如 ,那么最小费用方案中每条 流量必为 ,将求得最小值加上 即可。
#include <bits/stdc++.h> using namespace std; #define fi first #define se second #define TIME 1e3 * clock() / CLOCKS_PER_SEC using ll = long long; using uint = unsigned int; using lll = __int128; using pii = pair<int, int>; using pll = pair<ll, ll>; using ull = unsigned long long; inline ll read() { ll x = 0, sgn = 0; char s = getchar(); while(!isdigit(s)) sgn |= s == '-', s = getchar(); while(isdigit(s)) x = x * 10 + s - '0', s = getchar(); return sgn ? -x : x; } inline void print(int x) { if(x < 0) return putchar('-'), print(-x); if(x >= 10) print(x / 10); putchar(x % 10 + '0'); } bool Mbe; constexpr int N = 200 + 5; constexpr int M = 1e4 + 5; constexpr int inf = 1e7; struct flow { int cnt = 1, hd[N], nxt[M << 1], to[M << 1], limit[M << 1], cst[M << 1]; void add(int u, int v, int w, int c) { nxt[++cnt] = hd[u], hd[u] = cnt, to[cnt] = v, limit[cnt] = w, cst[cnt] = c; nxt[++cnt] = hd[v], hd[v] = cnt, to[cnt] = u, limit[cnt] = 0, cst[cnt] = -c; } int in[N], dis[N], fr[N]; int mincost(int S, int T) { int cost = 0; while(1) { queue<int> q; memset(dis, 0x3f, sizeof(dis)); dis[S] = 0, q.push(S); while(!q.empty()) { int t = q.front(); q.pop(), in[t] = 0; for(int i = hd[t]; i; i = nxt[i]) { int it = to[i], d = dis[t] + cst[i]; if(limit[i] && d < dis[it]) { dis[it] = d, fr[it] = i; if(!in[it]) q.push(it), in[it] = 1; } } } if(dis[T] > 1e9) return cost; int fl = 1064; for(int i = T; i != S; i = to[fr[i] ^ 1]) fl = min(fl, limit[fr[i]]); for(int i = T; i != S; i = to[fr[i] ^ 1]) limit[fr[i]] -= fl, limit[fr[i] ^ 1] += fl; cost += fl * dis[T]; } } } g; int n, k; bool Med; int main() { fprintf(stderr, "%.3lf MB\n", (&Mbe - &Med) / 1048576.0); #ifdef ALEX_WEI FILE* IN = freopen("1.in", "r", stdin); FILE* OUT = freopen("1.out", "w", stdout); #endif cin >> n >> k; int T = n * 2 + 2; for(int i = 0; i < n; i++) for(int j = i + 1; j <= n; j++) g.add(i * 2 + 1, j * 2, 1, read()); for(int i = 1; i <= n; i++) g.add(i * 2, i * 2 + 1, 1, -inf), g.add(i * 2 + 1, T, 1, 0); int ans = 1e9, cur = 0; for(int i = 1; i <= k; i++) { g.add(0, 1, 1, 0); ans = min(ans, cur += g.mincost(0, T)); } cout << ans + inf * n << endl; cerr << TIME << " ms\n"; return 0; } /* 2022/9/25 author: Alex_Wei start coding at 7:52 finish debugging at 8:15 */
- 1
信息
- ID
- 6054
- 时间
- 2000ms
- 内存
- 500MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者