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&&delta;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 }

 

你可能感兴趣的:(ZOJ)