BZOJ3532: [Sdoi2014]Lis
感谢ZYF神犇的耐心解答……
如果这题只要求最小代价……那就是一个比较明显的拆点最小割,对于所有\(j<i、a[j]<a[i]、f_i=f_j+1\)的\(i\)和\(j\)之间连一条边。
但是题目要求字典序最小,我们要用退流算法。
我们考虑从点\(i\)到\(i'\)的一条满流边,它是最小割中的边当且仅当不能从\(i\)增广到\(i'\)。
退流的话也不难,直接从\(T\)到\(i'\)和\(i\)到\(S\)做两次最大流,再删掉\(i\)到\(i'\)这条边。
1 /************************************************************** 2 Problem: 3532 3 User: zhuohan123 4 Language: C++ 5 Result: Accepted 6 Time:9472 ms 7 Memory:18660 kb 8 ****************************************************************/ 9 10 #include <iostream> 11 #include <cstdio> 12 #include <cstring> 13 #include <algorithm> 14 using namespace std; 15 typedef long long LL; 16 const int maxpoint=11000,maxedge=1100000; 17 const LL inf=~0ULL>>3; 18 int head[maxpoint],nowhead[maxpoint],pointsize; 19 struct edge{int to,next;LL c;}g[maxedge];int gnum=1; 20 void addedge(int from,int to,LL c) 21 { 22 g[++gnum].to=to;g[gnum].c=c;g[gnum].next=head[from];head[from]=gnum; 23 g[++gnum].to=from;g[gnum].c=0;g[gnum].next=head[to];head[to]=gnum; 24 } 25 int dfsstart,dfsend,dis[maxpoint]; 26 int q[maxpoint],ql,qr; 27 bool BFS() 28 { 29 for(int i=1;i<=pointsize;i++)nowhead[i]=head[i],dis[i]=0; 30 ql=1;qr=0;q[++qr]=dfsend; 31 while(ql<=qr) 32 for(int now=q[ql++],i=head[now];i;i=g[i].next) 33 if(g[i^1].c&&!dis[g[i].to]&&g[i].to!=dfsend) 34 dis[q[++qr]=g[i].to]=dis[now]+1; 35 return dis[dfsstart]; 36 } 37 LL DFS(int po,LL delta) 38 { 39 if(po==dfsend)return delta; 40 LL nowans=0,tans; 41 for(int&i=nowhead[po];i&δi=g[i].next) 42 if(g[i].c&&dis[g[i].to]+1==dis[po]&&(tans=DFS(g[i].to,min(delta,g[i].c)))) 43 g[i].c-=tans,g[i^1].c+=tans,nowans+=tans,delta-=tans; 44 return nowans; 45 } 46 LL dinic(int start,int end) 47 { 48 dfsstart=start,dfsend=end; 49 LL ans=0; 50 while(BFS())ans+=DFS(start,inf); 51 return ans; 52 } 53 int n; 54 int a[1100],b[1100],f[1100]; 55 struct T 56 { 57 int num,pos; 58 friend bool operator<(T A,T B){return A.num<B.num;} 59 }c[1100]; 60 int oans[1100],ansnum; 61 int main(int argc, char *argv[]) 62 { 63 //freopen("1.in","r",stdin); 64 //freopen("1.out","w",stdout); 65 int Ti;scanf("%d",&Ti); 66 while(Ti--) 67 { 68 memset(head,0,sizeof head);gnum=1; 69 scanf("%d",&n); 70 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 71 for(int i=1;i<=n;i++)scanf("%d",&b[i]); 72 for(int i=1;i<=n;i++)scanf("%d",&c[i].num),c[i].pos=i; 73 int maxf=0; 74 for(int i=1;i<=n;i++)f[i]=1; 75 for(int i=1;i<=n;i++) 76 for(int j=1;j<i;j++) 77 if(a[j]<a[i])maxf=max(maxf,f[i]=max(f[i],f[j]+1)); 78 for(int i=1;i<=n;i++) 79 { 80 addedge(2*i+1,2*i+2,b[i]); 81 if(f[i]==1)addedge(1,2*i+1,inf); 82 if(f[i]==maxf)addedge(2*i+2,2,inf); 83 for(int j=1;j<i;j++) 84 if(a[j]<a[i]&&(f[j]+1==f[i])) 85 addedge(2*j+2,2*i+1,inf); 86 } 87 pointsize=2*n+2; 88 LL ans=dinic(1,2); 89 sort(c+1,c+n+1); 90 ansnum=0; 91 for(int i=1;i<=n;i++) 92 { 93 int ne=0,po=c[i].pos; 94 for(int j=head[2*po+1];j;j=g[j].next) 95 if(g[j].to==2*po+2){ne=j;break ;} 96 if(g[ne].c==0) 97 { 98 dfsstart=2*po+1,dfsend=2*po+2; 99 if(!BFS()) 100 { 101 dinic(2,2*po+2); 102 dinic(2*po+1,1); 103 g[ne^1].c=0; 104 oans[++ansnum]=po; 105 } 106 } 107 } 108 sort(oans+1,oans+ansnum+1); 109 printf("%lld %d\n",ans,ansnum); 110 for(int i=1;i<ansnum;i++)printf("%d ",oans[i]);printf("%d\n",oans[ansnum]); 111 112 } 113 return 0; 114 }