BZOJ 4873 寿司餐厅 网络流
最大权闭合子图
1.每个区间收益(i,j)对应一个点 权值为正连S 负连T
2.每个区间收益向其子区间收益(i+1,j)与(i,j-1)对应的两个点连边 容量为INF
3.每个寿司类型对应一个点 连一条边到T 容量为m*w[i]*w[i]
4.每个寿司对应的区间收益点(i,i)连一条边到对应的寿司类型 容量为INF 再连一条边到T 容量为w[i]
最后跑最大流
//Netflow dumpling #include<bits/stdc++.h> using namespace std; const int MAXN = 11111; const int MAXM = 100000; const int INF = 1000000050; int Head[MAXN], cur[MAXN], lev[MAXN], to[MAXM << 1], nxt[MAXM << 1], f[MAXM << 1], ed = 1, S, T; inline void addedge(int u, int v, int cap) { to[++ed] = v; nxt[ed] = Head[u]; Head[u] = ed; f[ed] = cap; to[++ed] = u; nxt[ed] = Head[v]; Head[v] = ed; f[ed] = 0; return; } inline bool BFS() { int u; memset(lev, -1, sizeof(lev)); queue<int>q; lev[S] = 0; q.push(S); while (q.size()) { u = q.front(); q.pop(); for (int i = Head[u]; i; i = nxt[i]) if (f[i] && lev[to[i]] == -1) { lev[to[i]] = lev[u] + 1; q.push(to[i]); /* if (to[i] == T) { return 1; } magic one way optimize */ } } memcpy(cur, Head, sizeof Head); return lev[T] != -1; } inline int DFS(int u, int maxf) { if (u == T || !maxf) { return maxf; } int cnt = 0; for (int &i = cur[u], tem; i; i = nxt[i]) if (f[i] && lev[to[i]] == lev[u] + 1) { tem = DFS(to[i], min(maxf, f[i])); maxf -= tem; f[i] -= tem; f[i ^ 1] += tem; cnt += tem; if (!maxf) { break; } } if (!cnt) { lev[u] = -1; } return cnt; } int Dinic() { int ans = 0; while (BFS()) { ans += DFS(S, 2147483647); } return ans; } void init(int SS, int TT) { memset(Head, 0, sizeof(Head)); ed = 1; S = SS; T = TT; return; } int n, m, now; bool ok[1005]; int a[105]; int getid(int x, int y) { return 1000 + n * (x - 1) + y; } int main() { int ans = 0; scanf("%d %d", &n, &m); S = 0, T = n * n + 1005; for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); if (!ok[a[i]]) { addedge(a[i], T, m * a[i]*a[i]), ok[a[i]] = 1; } addedge(getid(i, i), a[i], INF); addedge(getid(i, i), T, a[i]); } for (int i = 1; i <= n; i++) { for (int j = i; j <= n; j++) { scanf("%d", &now); if (now > 0) { addedge(S, getid(i, j), now); ans += now; } else { addedge(getid(i, j), T, -now); } if (i != j) { addedge(getid(i, j), getid(i + 1, j), INF); addedge(getid(i, j), getid(i, j - 1), INF); } } } ans -= Dinic(); printf("%d\n", ans); return 0; }