题目传送门
题解
- 直接建图跑网络流即可。
- 对于区间的最大流,可以使用线段树,也可以直接加边。
- 注意数据范围不要太小。(奇奇怪怪,开小一点就超时???什么毛病)
AC-Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int inf = 0x3f3f3f3f;
const int maxn = 1e6 + 7;
struct Edge {
int to;
int next;
int val;
};
struct Dinic {
Edge edge[maxn << 1];
int head[maxn];
int cnt;
int depth[maxn];
void init() {
memset(head, -1, sizeof(head));
cnt = 0;
}
void add(int u, int v, int w) {
edge[cnt].to = v;
edge[cnt].next = head[u];
edge[cnt].val = w;
head[u] = cnt++;
}
bool bfs(int s, int t) {
queue<int>q;
memset(depth, 0, sizeof depth);
depth[s] = 1;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (edge[i].val > 0 && depth[v] == 0) {
depth[v] = depth[u] + 1;
q.push(v);
}
}
}
return depth[t];
}
int dfs(int u, int flow, int t) {
if (u == t || flow <= 0)
return flow;
int rest = flow;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (depth[v] == depth[u] + 1 && edge[i].val != 0) {
int k = dfs(v, min(rest, edge[i].val), t);
rest -= k;
edge[i].val -= k;
edge[i ^ 1].val += k;
}
}
return flow - rest;
}
int maxflow(int s, int t) {
int ans = 0;
while (bfs(s, t)) {
while (int d = dfs(s, inf, t))
ans += d;
}
return ans;
}
}DC;
int sum[maxn];
int main() {
ios;
int t; cin >> t;
while (t--) {
DC.init();
int n, m, k; cin >> n >> m >> k;
for (int i = 0; i <= k; ++i) sum[i] = 0;
for (int i = 0; i < n; ++i) {
int x; cin >> x;
++sum[x];
}
int num = k;
for (int i = 1; i <= m; ++i) {
int op, c; cin >> op >> c;
if (op == 1) {
int a0, b0; cin >> a0 >> b0;
DC.add(a0, b0, c); DC.add(b0, a0, 0);
}
else if (op == 2) {
int a1, a2, b1; cin >> a1 >> a2 >> b1;
++num;
for (int j = a1; j <= a2; ++j) {
DC.add(j, num, c); DC.add(num, j, 0);
}
DC.add(num, b1, c); DC.add(b1, num, 0);
}
else if (op == 3) {
int a1, b1, b2; cin >> a1 >> b1 >> b2;
++num;
DC.add(a1, num, c); DC.add(num, a1, 0);
for (int j = b1; j <= b2; ++j) {
DC.add(num, j, c); DC.add(j, num, 0);
}
}
else if (op == 4) {
int a1, a2, b1, b2; cin >> a1 >> a2 >> b1 >> b2;
++num;
for (int j = a1; j <= a2; ++j) {
DC.add(j, num, c); DC.add(num, j, 0);
}
DC.add(num, num + 1, c); DC.add(num + 1, num, 0);
++num;
for (int j = b1; j <= b2; ++j) {
DC.add(num, j, c); DC.add(j, num, 0);
}
}
}
int start = 0, end = ++num;
for (int i = 1; i <= k; ++i) {
if (sum[i]) {
DC.add(start, i, sum[i]); DC.add(i, start, 0);
}
}
DC.add(k, end, n); DC.add(end, k, 0);
cout << DC.maxflow(start, end) << endl;
}
}