题意:
给定序列A,序列中的每一项Ai有删除代价Bi和附加属性Ci。请删除若干项,使得4的最长上升子序列长度减少至少1,且付出的代价之和最小,并输出方案。
如果有多种方案,请输出将删去项的附加属性排序之后,字典序最小的一种。
题解:
假如没有字典序最小这个限制,直接拆点+最小割就好了。
然而还要字典序最小。
所以将C排序,从小到大删边,每删掉一条割边就将流量退回来。
具体代码,挺好理解的。
code:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
#define LL long long
using namespace std;
const int inf=(1<<28);
struct NODE{
int x,y,next,c,ot;
}a[1000010];int len,last[1510];
struct node{
int a,b,c,id;
}p[710];
int n,f[710];
void ins(int x,int y,int c)
{
a[++len].y=y;a[len].c=c;a[len].x=x;
a[len].next=last[x];last[x]=len;
a[++len].y=x;a[len].c=0;a[len].x=y;
a[len].next=last[y];last[y]=len;
}
queue<int> q;
int st,ed,h[1510];
bool bt_h(int st,int ed)
{
memset(h,0,sizeof(h));
h[st]=1;
while(!q.empty()) q.pop();
q.push(st);
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(a[i].c&&h[y]==0)
h[y]=h[x]+1,q.push(y);
}
}
return h[ed]!=0;
}
int findflow(int x,int f,int st,int ed)
{
if(x==ed) return f;
int ans=0,t;
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(ans<f&&a[i].c&&h[y]==h[x]+1)
a[i].c-=(t=findflow(y,min(a[i].c,f-ans),st,ed)),a[i^1].c+=t,ans+=t;
}
if(!ans) h[x]=0;
return ans;
}
int dinic(int st,int ed)
{
int ans=0,t;
while(bt_h(st,ed))
while(t=findflow(st,inf,st,ed)) ans+=t;
return ans;
}
bool cmp(node a,node b) {return a.c<b.c;}
int ans[710],num=0;
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&p[i].a);
for(int i=1;i<=n;i++) scanf("%d",&p[i].b);
for(int i=1;i<=n;i++) scanf("%d",&p[i].c),p[i].id=i;
len=1;st=0;ed=2*n+1;
memset(last,0,sizeof(last));
int Max=0;
for(int i=1;i<=n;i++)
{
f[i]=0;
for(int j=1;j<i;j++)
if(p[j].a<p[i].a) f[i]=max(f[i],f[j]);
f[i]++;
}
for(int i=1;i<=n;i++) Max=max(Max,f[i]);
for(int i=1;i<=n;i++) ins(i,i+n,p[i].b);
for(int i=1;i<=n;i++)
{
if(f[i]==Max) ins(i+n,ed,inf);
if(f[i]==1) ins(st,i,inf);
}
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
if(f[j]+1==f[i]&&p[j].a<p[i].a) ins(j+n,i,inf);
int fl=dinic(st,ed);sort(p+1,p+n+1,cmp);num=0;
for(int i=1,x;i<=n;i++)
{
x=p[i].id;
if(a[x*2].c||bt_h(x,x+n)) continue;
ans[++num]=x;
dinic(ed,x+n),dinic(x,st);
a[x*2].c=a[(x*2)^1].c=0;
}
sort(ans+1,ans+num+1);
printf("%d %d\n",fl,num);
for(int i=1;i<num;i++) printf("%d ",ans[i]);printf("%d\n",ans[num]);
}
}