3532: [Sdoi2014]Lis
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 838 Solved: 303
[ Submit][ Status][ Discuss]
Description
给定序列A,序列中的每一项Ai有删除代价Bi和附加属性Ci。请删除若
干项,使得4的最长上升子序列长度减少至少1,且付出的代价之和最小,并输出方案。
如果有多种方案,请输出将删去项的附加属性排序之后,字典序最小的一种。
Input
输入包含多组数据。
输入的第一行包含整数T,表示数据组数。接下来4*T行描述每组数据。
每组数据的第一行包含一个整数N,表示A的项数,接下来三行,每行N个整数A1..An,B1.,Bn,C1..Cn,满足1 < =Ai,Bi,Ci < =10^9,且Ci两两不同。
Output
对每组数据,输出两行。第一行包含两个整数S,M,依次表示删去项的代价和与数量;接下来一行M个整数,表示删去项在4中的的位置,按升序输出。
Sample Input
1
6
3 4 4 2 2 3
2 1 1 1 1 2
6 5 4 3 2 1
6
3 4 4 2 2 3
2 1 1 1 1 2
6 5 4 3 2 1
Sample Output
4 3
2 3 6
解释:删去(A2,43,A6),(A1,A6),(A2,43,44,A5)等都是合法的方案,但
{A2,43,A6)对应的C值的字典序最小。
2 3 6
解释:删去(A2,43,A6),(A1,A6),(A2,43,44,A5)等都是合法的方案,但
{A2,43,A6)对应的C值的字典序最小。
HINT
1 < =N < =700 T < =5
Source
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
//#include<ctime>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 1505;
const int maxm = 4E5 + 40;
typedef int LL;
const int INF = ~0U>>1;
struct E{
int to; int cap,flow; E(){}
E(int to,LL cap,LL flow): to(to),cap(cap),flow(flow){}
}edgs[maxm];
struct data{
int Num,key; data(){}
data(int Num,int key): Num(Num),key(key){}
bool operator < (const data &B) const {return key < B.key;}
}D[maxn];
int n,m,tot,cnt,Cnt,T,s,t,tp,Ans[maxn],A[maxn],B[maxn],cur[maxn]
,L[maxn],f[maxn],a[maxn],b[maxn],id[maxn],vis[maxn];
vector <int> v[maxn];
queue <int> Q;
int getint()
{
char ch = getchar(); int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret * 10 + ch - '0',ch = getchar();
return ret;
}
char ch[20];
void Print(LL x)
{
if (!x) {putchar('0'); return;} int len = 0;
while (x) ch[++len] = x % 10LL,x /= 10LL;
for (int i = len; i; i--) putchar(ch[i] + '0');
}
bool BFS(int ss,int tt)
{
for (int i = 0; i <= tot; i++) L[i] = 0;
Q.push(ss); L[ss] = 1;
while (!Q.empty())
{
int k = Q.front(); Q.pop();
for (int i = 0; i < v[k].size(); i++)
{
E e = edgs[v[k][i]];
if (e.cap == e.flow || L[e.to]) continue;
L[e.to] = L[k] + 1; Q.push(e.to);
}
}
return L[tt];
}
LL Dinic(int x,LL res,int tt)
{
if (x == tt) return res; LL flow = 0;
for (int &i = cur[x]; i < v[x].size(); i++)
{
E &e = edgs[v[x][i]];
if (e.cap == e.flow || L[e.to] != L[x] + 1) continue;
LL f = Dinic(e.to,min(res,e.cap - e.flow),tt);
if (!f) continue; flow += f; e.flow += f;
edgs[v[x][i]^1].flow -= f; res -= f;
if (!res) return flow;
}
if (!flow) L[x] = -1; return flow;
}
LL MaxFlow(int ss,int tt)
{
LL ret = 0;
while (BFS(ss,tt))
{
for (int i = 0; i <= tot; i++) cur[i] = 0;
ret += Dinic(ss,INF,tt);
}
return ret;
}
bool Check(int x)
{
vis[A[x]] = ++Cnt; Q.push(A[x]);
while (!Q.empty())
{
int k = Q.front(); Q.pop();
for (int i = 0; i < v[k].size(); i++)
{
E e = edgs[v[k][i]];
if (e.cap == e.flow || vis[e.to] == Cnt) continue;
vis[e.to] = Cnt; Q.push(e.to);
}
}
return vis[B[x]] != Cnt;
}
void Work(int x)
{
MaxFlow(t,B[x]); MaxFlow(A[x],s);
edgs[id[x]].cap = edgs[id[x]].flow = 0;
edgs[id[x]^1].cap = edgs[id[x]^1].flow = 0;
}
void Add(int x,int y,LL cap)
{
v[x].push_back(cnt); edgs[cnt++] = E(y,cap,0);
v[y].push_back(cnt); edgs[cnt++] = E(x,0,0);
}
void Clear()
{
for (int i = 0; i <= tot; i++) v[i].clear();
memset(f,0,sizeof(f)); tot = tp = cnt = 0;
}
void Solve()
{
n = getint(); int Max = 0;
for (int i = 1; i <= n; i++) A[i] = ++tot,B[i] = ++tot; t = ++tot;
for (int i = 1; i <= n; i++) a[i] = getint();
for (int i = 1; i <= n; i++) b[i] = getint();
for (int i = 1; i <= n; i++) D[i] = data(i,getint());
sort(D + 1,D + n + 1);
for (int i = 2; i <= n; i++)
{
for (int j = 1; j < i; j++)
if (a[i] > a[j]) f[i] = max(f[i],f[j] + 1);
Max = max(Max,f[i]);
}
for (int i = 1; i <= n; i++)
if (f[i] == Max) Add(B[i],t,INF);
for (int i = 1; i <= n; i++)
{
if (!f[i]) Add(s,A[i],INF);
for (int j = i + 1; j <= n; j++)
if (a[i] < a[j] && f[i] + 1 == f[j])
Add(B[i],A[j],INF);
Add(A[i],B[i],b[i]); id[i] = cnt - 1;
}
LL sum = MaxFlow(s,t);
//cerr << (double)(clock()) / CLOCKS_PER_SEC << endl;
for (int i = 1; i <= n; i++)
if (Check(D[i].Num))
{
Work(D[i].Num); Ans[++tp] = D[i].Num;
//cerr << (double)(clock()) / CLOCKS_PER_SEC << endl;
}
sort(Ans + 1,Ans + tp + 1);
Print(sum); putchar(' '); Print(tp); puts("");
for (int i = 1; i < tp; i++) Print(Ans[i]),putchar(' ');
Print(Ans[tp]); puts(""); Clear();
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
T = getint(); while (T--) Solve();
//cerr << (double)(clock()) / CLOCKS_PER_SEC << endl;
return 0;
}