链接:https://ac.nowcoder.com/acm/contest/5758/G
来源:牛客网
小明是一个魔法师,他有n棵植物,所有植物排成一排,植物的初始高度为数组h,小明有一些强迫症,他想
让植物的高度都恰好达到k,小明有m瓶药水,但药水分为4种:
1.选择一棵高度为a0的植物变为b0高度的植物
2.选择一棵高度在[a1,a2]区间内的植物变为b1高度的植物
3.选择一棵高度为a1的植物变为[b1, b2]区间内某一高度的植物
4.选择一棵高度在[a1,a2]区间内的植物变为[b1,b2]区间内某一高度的植物
由于每瓶药水有C瓶库存,小明想知道他最多让多少棵植物高度达到k
输入描述:
输入数据第一行是t,表示数据的组数,接下来每组数据输入n,m,k,
接下来一行输入n个数,分别是每棵植物的高度h[i](1 <= h[i] < k),
接下来m行开头的两个数字为op和c表示药水是哪一种和该种药水有几瓶,输入如下
若 op=1,则接下来两个整数 a0,b0,意义如上文所述。
若 op=2,则接下来三个整数 a1,a2,b1,意义如上文所述。
若 op=3,则接下来三个整数 a1,b1,b2,意义如上文所述。
若 op=4,则接下来四个整数 a1,a2,b1,b2,意义如上文所述。
数据保证,所有 1 <= a0,b0,a1,b1,a2,b2 <= k
(t <= 10,n <= 1e4,m <= 300,k <= 100,c <=1e6)
输出描述:
输出一个整数,表示最多有多少颗植物能生涨到k。
示例1
输入
复制
1
5 4 5
1 1 1 1 1
1 3 1 3
1 3 3 2
1 3 2 5
4 1 1 1 4 5
输出
复制
4
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 100;
const int mod = 1e9 + 7;
ll qp(ll a, ll n, ll mod = ::mod) {
ll res = 1;
while (n > 0) {
if (n & 1) res = res * a % mod;
a = a * a % mod;
n >>= 1;
}
return res;
}
const int MAX_V = 2000 + 10;
const int INF = 0x3f3f3f3f;
//用于表示边的结构体(终点,流量,反向边)
struct edge {
int to;
ll cap;
int rev;
};
vector<edge> G[MAX_V]; //图的邻接表表示
int level[MAX_V]; //顶点到源点的距离标号
int iter[MAX_V]; //当前弧
void add(int from, int to, ll cap) {
// cerr << from << " " << to << " " << cap << endl;
G[from].push_back((edge) {to, cap, (int) G[to].size()});
G[to].push_back((edge) {from, 0, (int) G[from].size() - 1});
}
//计算从源点出发的距离标号
void bfs(int s) {
memset(level, -1, sizeof(level));
queue<int> que;
level[s] = 0;
que.push(s);
while (!que.empty()) {
int v = que.front();
que.pop();
for (int i = 0; i < G[v].size(); i++) {
edge &e = G[v][i];
if (e.cap > 0 && level[e.to] < 0) {
level[e.to] = level[v] + 1;
que.push(e.to);
}
}
}
}
//通过DFS寻找增广路
ll dfs(int v, int t, ll f) {
if (v == t) return f;
for (int &i = iter[v]; i < G[v].size(); i++) {
edge &e = G[v][i];
if (e.cap > 0 && level[v] < level[e.to]) {
ll d = dfs(e.to, t, min(f, e.cap));
if (d > 0) {
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
//求解从s到t的最大流
ll max_flow(int s, int t) {
ll flow = 0;
for (;;) {
bfs(s);
if (level[t] < 0) return flow;
memset(iter, 0, sizeof(iter));
ll f;
while ((f = dfs(s, t, INF)) > 0) flow += f;
}
}
int main(int argc, char *argv[]) {
int TT;
scanf("%d", &TT);
for (int kase = 1; kase <= TT; ++kase) {
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
int S = 0;
int tot = k;
vector<int> tmp(n);
for (int i = 0; i < n; ++i) {
scanf("%d", &tmp[i]);
}
sort(tmp.begin(), tmp.end());
int pre = tmp[0], tt = 1;
for (int i = 1; i < n; ++i) {
if (pre == tmp[i]) {
tt++;
} else {
add(S, pre, tt);
pre = tmp[i];
tt = 1;
}
}
add(S, pre, tt);
for (int i = 0; i < m; ++i) {
int op;
scanf("%d", &op);
if (op == 1) {
int tx, a0, b0;
scanf("%d%d%d", &tx, &a0, &b0);
tx = min(tx, n);
add(a0, b0, tx);
} else if (op == 2) {
int tx, a1, a2, b1;
scanf("%d%d%d%d", &tx, &a1, &a2, &b1);
tx = min(tx, n);
add(++tot, b1, tx);
for (int j = a1; j <= a2; ++j) add(j, tot, tx);
} else if (op == 3) {
int tx, a1, b1, b2;
scanf("%d%d%d%d", &tx, &a1, &b1, &b2);
tx = min(tx, n);
add(a1, ++tot, tx);
for (int j = b1; j <= b2; ++j) add(tot, j, tx);
} else {
int tx, a1, a2, b1, b2;
scanf("%d%d%d%d%d", &tx, &a1, &a2, &b1, &b2);
tx = min(tx, n);
int tot1 = ++tot;
int tot2 = ++tot;
add(tot1, tot2, tx);
for (int j = a1; j <= a2; ++j) add(j, tot1, tx);
for (int j = b1; j <= b2; ++j) add(tot2, j, tx);
}
}
printf("%lld\n", max_flow(0, k));
for (int i = 0; i <= tot; ++i) {
G[i].clear();
}
}
return 0;
}