题目大意
题目已经说得很清楚了qwq。
题解
首先我们考虑如何计算出最少删除的代价。
考虑在dp的过程中,如果
i
i
i能够使
j
j
j取到最大值,就连边
(
i
,
j
)
(i,j)
(i,j),容易发现,题目就是问去掉一些点使左右不连通求最小代价。
于是拆点连边跑最小割即可。
但是题目还要字典序最小,我们考虑按C从小到大排序,判断当前边是否在割中,如果在,就割掉。然鹅我们必须及时更新每条边的剩余容量,因此每次割掉之后还要跑最大流。但是这样显然会T,于是就需要退流。
把
(
u
,
v
)
(u,v)
(u,v)删掉后退流的过程就是跑
u
→
S
u\rightarrow S
u→S的最大流,再跑
T
→
v
T\rightarrow v
T→v的最大流即可。
然后就过了。
#include <bits/stdc++.h>
using namespace std;
const int MAXR = 10000000;
char _READ_[MAXR], _PRINT_[MAXR];
int _READ_POS_, _PRINT_POS_, _READ_LEN_;
inline char readc() {
#ifndef ONLINE_JUDGE
return getchar();
#endif
if (!_READ_POS_) _READ_LEN_ = fread(_READ_, 1, MAXR, stdin);
char c = _READ_[_READ_POS_++];
if (_READ_POS_ == MAXR) _READ_POS_ = 0;
if (_READ_POS_ > _READ_LEN_) return 0;
return c;
}
template<typename T> inline void read(T &x) {
x = 0; register int flag = 1, c;
while (((c = readc()) < '0' || c > '9') && c != '-');
if (c == '-') flag = -1; else x = c - '0';
while ((c = readc()) >= '0' && c <= '9') x = x * 10 + c - '0';
x *= flag;
}
template<typename T1, typename ...T2> inline void read(T1 &a, T2&... x) {
read(a), read(x...);
}
inline int reads(char *s) {
register int len = 0, c;
while (isspace(c = readc()) || !c);
s[len++] = c;
while (!isspace(c = readc()) && c) s[len++] = c;
s[len] = 0;
return len;
}
inline void ioflush() { fwrite(_PRINT_, 1, _PRINT_POS_, stdout), _PRINT_POS_ = 0; fflush(stdout); }
inline void printc(char c) {
_PRINT_[_PRINT_POS_++] = c;
if (_PRINT_POS_ == MAXR) ioflush();
}
inline void prints(char *s) {
for (int i = 0; s[i]; i++) printc(s[i]);
}
template<typename T> inline void print(T x, char c = '\n') {
if (x < 0) printc('-'), x = -x;
if (x) {
static char sta[20];
register int tp = 0;
for (; x; x /= 10) sta[tp++] = x % 10 + '0';
while (tp > 0) printc(sta[--tp]);
} else printc('0');
printc(c);
}
template<typename T1, typename ...T2> inline void print(T1 x, T2... y) {
print(x, ' '), print(y...);
}
typedef long long ll;
const int MAXN = 2005, MAXM = 1000005, INF = 0x3f3f3f3f;
struct Edge { int to, cap, next; } edge[MAXM];
int head[MAXN], que[MAXN], dis[MAXN], vis[MAXN], tot;
void addedge(int u, int v, int c) {
edge[tot] = (Edge) { v, c, head[u] };
head[u] = tot++;
edge[tot] = (Edge) { u, 0, head[v] };
head[v] = tot++;
}
bool bfs(int s, int t) {
int he = 0, ta = 0;
memset(dis, -1, sizeof(dis));
dis[que[ta++] = s] = 0;
while (he < ta) {
int u = que[he++];
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (edge[i].cap && dis[v] < 0) {
dis[que[ta++] = v] = dis[u] + 1;
if (v == t) return 1;
}
}
}
return 0;
}
int dfs(int u, int t, int f) {
if (u == t) return f;
int flow = 0;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (edge[i].cap > 0 && dis[v] > dis[u]) {
int d = dfs(v, t, min(f, edge[i].cap));
if (d == 0) continue;
f -= d, flow += d;
edge[i].cap -= d, edge[i ^ 1].cap += d;
if (f == 0) return flow;
}
}
if (flow == 0) dis[u] = -1;
return flow;
}
int dinic(int s, int t) {
int flow = 0;
while (bfs(s, t)) flow += dfs(s, t, INF);
return flow;
}
int A[MAXN], B[MAXN], C[MAXN], f[MAXN], arr[MAXN], n, T;
bool cmp(int x, int y) { return C[x] < C[y]; }
void cut(int x) {
for (int i = head[x * 2 - 1]; ~i; i = edge[i].next)
if (edge[i].to == x * 2) edge[i].cap = edge[i ^ 1].cap = 0;
}
int main() {
for (read(T); T--;) {
read(n);
memset(head, -1, sizeof(head)); tot = 0;
for (int i = 1; i <= n; i++) read(A[i]);
for (int i = 1; i <= n; i++) read(B[i]);
for (int i = 1; i <= n; i++) read(C[i]);
int s = n * 2 + 1, t = s + 1, mx = 0;
for (int i = 1; i <= n; i++) {
f[i] = 1;
for (int j = 1; j < i; j++)
if (A[j] < A[i]) f[i] = max(f[i], f[j] + 1);
for (int j = 1; j < i; j++)
if (A[j] < A[i] && f[j] + 1 == f[i]) addedge(j * 2, i * 2 - 1, INF);
addedge(i * 2 - 1, i * 2, B[i]);
if (f[i] == 1) addedge(s, i * 2 - 1, INF);
mx = max(mx, f[i]);
}
for (int i = 1; i <= n; i++) if (f[i] == mx) addedge(i * 2, t, INF);
print(dinic(s, t), ' ');
for (int i = 1; i <= n; i++) arr[i] = i;
sort(arr + 1, arr + 1 + n, cmp);
vector<int> ans;
for (int i = 1; i <= n; i++) {
int x = arr[i];
if (bfs(x * 2 - 1, x * 2)) continue;
cut(x), dinic(x * 2 - 1, s), dinic(t, x * 2);
ans.push_back(x);
}
print(ans.size());
sort(ans.begin(), ans.end());
for (int i : ans) print(i, ' ');
printc('\n');
}
ioflush();
return 0;
}