給定序列A,序列中的每一項Ai有刪除代價Bi和附加屬性Ci。請刪除若干項,使得4的最長上升子序列長度減小至少1,且付出的代價之和最小,並輸出方案。
若是有多種方案,請輸出將刪去項的附加屬性排序以後,字典序最小的一種。
php
給定序列A,序列中的每一項Ai有刪除代價Bi和附加屬性Ci。請刪除若干項,使得4的最長上升子序列長度減小至少1,且付出的代價之和最小,並輸出方案。
若是有多種方案,請輸出將刪去項的附加屬性排序以後,字典序最小的一種。
php
輸入包含多組數據。
輸入的第一行包含整數T,表示數據組數。接下來4*T行描述每組數據。
每組數據的第一行包含一個整數N,表示A的項數,接下來三行,每行N個整數A1..An,B1.,Bn,C1..Cn,知足1 < =Ai,Bi,Ci < =10^9,且Ci兩兩不一樣。
ios
對每組數據,輸出兩行。第一行包含兩個整數S,M,依次表示刪去項的代價和與數量;接下來一行M個整數,表示刪去項在4中的的位置,按升序輸出。
spa
1 < =N < =700 T < =5blog
最小割的模型仍是很顯然的,先dp一邊,而後轉移之間連邊,源點到初始狀態,最終狀態到匯點,拆點限制流量,最小割即刪去的代價。ip
而後考慮字典序最小的割,能夠經過按字典序枚舉每條限流邊,若是這條邊滿流且沒法再流過去,則這條割邊可選,而後消除它的影響,繼續處理。get
消除影響能夠利用退流的思想,其實就是將這條邊<u,v>正反置0,而後跑一遍T->v,一遍u->S便可。string
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 5010 int N,cas,a[MAXN],b[MAXN],c[MAXN]; struct EdgeNode{ int next,to,cap; }edge[2000100]; int head[MAXN],cnt=1; inline void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;} inline void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,0);} int h[MAXN],cur[MAXN],S,T; queue<int>q; inline bool bfs(int s,int t) { for (int i=S; i<=T; i++) h[i]=-1; q.push(s); h[s]=0; while (!q.empty()) { int now=q.front(); q.pop(); for (int i=head[now]; i; i=edge[i].next) if (edge[i].cap && h[edge[i].to]==-1) h[edge[i].to]=h[now]+1,q.push(edge[i].to); } return h[t]!=-1; } inline int dfs(int now,int low,int s,int t) { if (now==t) return low; int w,used=0; for (int i=cur[now]; i; i=edge[i].next) if (edge[i].cap && h[edge[i].to]==h[now]+1) { int w=dfs(edge[i].to,min(low-used,edge[i].cap),s,t); edge[i].cap-=w; edge[i^1].cap+=w; used+=w; if (used==low) return used; if (edge[i].cap) cur[now]=i; } if (!used) h[now]=-1; return used; } #define INF 0x7fffffff inline int Dinic(int s,int t) { int re=0; while (bfs(s,t)) { for (int i=S; i<=T; i++) cur[i]=head[i]; re+=dfs(s,INF,s,t); } return re; } #define Pa pair<int,int> #define MP make_pair #define Id first #define ps second inline bool cmp(Pa x,Pa y) {return c[x.Id]<c[y.Id];} int stack[MAXN],top=0; int main() { cas=read(); while (cas--) { cnt=1; memset(head,0,sizeof(head)); N=read(); for (int i=1; i<=N; i++) a[i]=read(); for (int i=1; i<=N; i++) b[i]=read(); for (int i=1; i<=N; i++) c[i]=read(); static int f[MAXN]; for (int i=1; i<=N; i++) f[i]=1; for (int i=1; i<=N; i++) for (int j=0; j<i; j++) if (a[i]>a[j]) f[i]=max(f[i],f[j]+1); int mx=0; for (int i=1; i<=N; i++) mx=max(mx,f[i]); S=0,T=2*N+1; static Pa id[MAXN]; for (int i=1; i<=N; i++) { if (f[i]==1) InsertEdge(S,i,INF); if (f[i]==mx) InsertEdge(i+N,T,INF); InsertEdge(i,i+N,b[i]); id[i]=MP(i,cnt); for (int j=1; j<i; j++) if (f[i]-1==f[j] && a[i]>a[j]) InsertEdge(j+N,i,INF); } int ans=Dinic(S,T); stable_sort(id+1,id+N+1,cmp); top=0; for (int i=1; i<=N; i++) { int e1=id[i].ps^1,e2=id[i].ps,p1=id[i].Id,p2=p1+N; if (!edge[e1].cap && !bfs(p1,p2)) { Dinic(p1,S); Dinic(T,p2); edge[e1].cap=edge[e2].cap=0; stack[++top]=id[i].Id; } } stable_sort(stack+1,stack+top+1); printf("%d %d\n",ans,top); for (int i=1; i<top; i++) printf("%d ",stack[i]); printf("%d\n",stack[top]); } return 0; }