• 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
    ",ans,ansnum);
    110         for(int i=1;i<ansnum;i++)printf("%d ",oans[i]);printf("%d
    ",oans[ansnum]);
    111          
    112     }
    113     return 0;
    114 }
  • 相关阅读:
    Win10导出查看删除已安装的证书
    Tomcat配置https访问
    SpringBoot启用https
    使用OpenSSL证书操作详解
    sed命令常用用法
    Jenkins安装第一个插件和通过离线安装包进行安装
    CentOS设置主机名称
    Jenkins使用过程中遇到的问题
    Visual Studio 最新插件
    文章去格式
  • 原文地址:https://www.cnblogs.com/zhuohan123/p/3772810.html
Copyright © 2020-2023  润新知