根据题意 每个点可以直接与S,T相连 也可以和前面的哨站相连 暴力建边的话 有n条边
要用分治优化建边:
类似于归并排序 先对每一层分为左半边与右半边 对每一半都拿出来先排序去重后 直接排成一条链建边
if (l == r) { return ; } int mid = (l + r) >> 1; solve(l, mid), solve(mid + 1, r); int cnt = 0; for (int i = l; i <= r; i++) { aa[++cnt] = a[i]; } sort(aa + 1, aa + 1 + cnt); cnt = unique(aa + 1, aa + cnt + 1) - aa - 1; int now = MCMF::MAXP; for (int i = 1; i < cnt; i++) { MCMF::addedge(now + i, now + i + 1, inf, aa[i + 1] - aa[i]); MCMF::addedge(now + i + 1, now + i, inf, aa[i + 1] - aa[i]); }
然后对于区间内的每个数 前半边的出后半边的入
for (int i = l; i <= r; i++) { int aim = lower_bound(aa + 1, aa + cnt + 1, a[i]) - aa; if (i <= mid) { MCMF::addedge(now + aim, i + n, 1, 0); } else { MCMF::addedge(i, now + aim, 1, 0); } }
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef long long JQK; const int inf = INT_MAX / 2; namespace MCMF { const JQK INF = LLONG_MAX / 2; const int MAXN = 50500, MAXM = 130000; int Head[MAXN], cur[MAXN], to[MAXM << 1], nxt[MAXM << 1], f[MAXM << 1], ed = 1; int S, T, MAXP, MAXF, pre[MAXN]; JQK lev[MAXN], cost[MAXM << 1]; bool exist[MAXN]; void addedge(int u, int v, int cap, JQK val) { //cout << u << " " << v << " " << cap << " " << val << endl; to[++ed] = v; nxt[ed] = Head[u]; Head[u] = ed; f[ed] = cap; cost[ed] = val; to[++ed] = u; nxt[ed] = Head[v]; Head[v] = ed; f[ed] = 0; cost[ed] = -1 * val; return; } bool spfa() { int u; queue<int>q; for (int i = 0; i <= MAXP + 1; i++) { exist[i] = 0; lev[i] = INF; } //memset(exist, false, sizeof(exist)); //memset(lev, 127, sizeof(lev)); lev[S] = pre[S] = 0; q.push(S); while (q.size()) { u = q.front(); q.pop(); exist[u] = false; for (int i = Head[u]; i; i = nxt[i]) if (f[i] && lev[u] + cost[i] < lev[to[i]]) { lev[to[i]] = lev[u] + cost[i]; pre[to[i]] = i; if (!exist[to[i]]) { exist[to[i]] = true; q.push(to[i]); } } } for (int i = 0; i <= MAXP + 1; i++) { cur[i] = Head[i]; } //memcpy(cur, Head, sizeof(Head)); return lev[T] != INF; } JQK Augment() { JQK delta = 0x7f7f7f7f; for (int i = pre[T]; i; i = pre[to[i ^ 1]]) if (f[i] < delta) { delta = f[i]; } for (int i = pre[T]; i; i = pre[to[i ^ 1]]) { f[i] -= delta; f[i ^ 1] += delta; } MAXF += delta; return delta * lev[T]; } void init(int S1, int T1) { MAXF = 0; S = S1; T = T1; return; } JQK MCMF() { JQK ans = 0; memset(exist, false, sizeof(exist)); while (spfa()) //ans+=DFS(S,INF)*lev[T]; { ans += Augment(); } return ans; } } inline void RR(int &x) { char c; bool sign = false; for (c = getchar(); c < '0' || c > '9'; c = getchar()) if (c == '-') { sign = true; } for (x = 0; c >= '0' && c <= '9'; c = getchar()) { x = x * 10 + c - '0'; } sign && (x = -x); } int n, a[1005], aa[1005]; void solve(int l, int r) { if (l == r) { return ; } int mid = (l + r) >> 1; solve(l, mid), solve(mid + 1, r); int cnt = 0; for (int i = l; i <= r; i++) { aa[++cnt] = a[i]; } sort(aa + 1, aa + 1 + cnt); cnt = unique(aa + 1, aa + cnt + 1) - aa - 1; int now = MCMF::MAXP; for (int i = 1; i < cnt; i++) { MCMF::addedge(now + i, now + i + 1, inf, aa[i + 1] - aa[i]); MCMF::addedge(now + i + 1, now + i, inf, aa[i + 1] - aa[i]); } for (int i = l; i <= r; i++) { int aim = lower_bound(aa + 1, aa + cnt + 1, a[i]) - aa; if (i <= mid) { MCMF::addedge(now + aim, i + n, 1, 0); } else { MCMF::addedge(i, now + aim, 1, 0); } } MCMF::MAXP += cnt; } int main() { int x; int s, t; ll W; RR(n), RR(x); W = x; MCMF::MAXP = 2 * n + 3, s = 2 * n + 1, t = 2 * n + 2; for (int i = 1; i <= n; i++) { RR(a[i]); MCMF::addedge(s, i, 1, 0), MCMF::addedge(i, t, 1, W), MCMF::addedge(i + n, t, 1, 0); } solve(1, n); MCMF::init(s, t); cout << MCMF::MCMF() << "\n"; return 0; }