zoukankan      html  css  js  c++  java
  • codevs1906 最长递增子序列问题

    题目描述 Description

    给定正整数序列x1,..... , xn  。
    (1)计算其最长递增子序列的长度s。
    (2)计算从给定的序列中最多可取出多少个长度为s的递增子序列。
    (3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长
    度为s的递增子序列。

    输入描述 Input Description

    第1 行有1个正整数n,表示给定序列的长度。接
    下来的1 行有n个正整数x1.....xn 。

    输出描述 Output Description

    第1 行是最长递增子序列的长度s。第2行是可取出的长度为s 的递增子序列个数。第3行是允许在取出的序列中多次使用x1和xn时可取出的长度为s 的递增子序列个数。

    样例输入 Sample Input

    4
    3 6 2 5

    样例输出 Sample Output

    2
    2
    3

     
     
    正解:建图+最大流

    解题报告:

      这道题的建图方式比较简单。第一问的话跑一下DP就可以了,nlogn的最长不下降子序列DPn^2也可以),可以求出最大长度maxl。第二问考虑能从原序列中取出多少个长度为maxl的不下降序列。显然当我们选择了某个元素a[i]时,我们下一个可以选择的a[j],则a[j]是不小于当前元素且f[j]+1=f[i],我们考虑如何建图能达到题意要求。首先每个元素肯定只能用一次,并且只能按照上述顺序选取。

      建图:每个点i我们拆成两个点i.ai.b。对于每个f[i]=maxli我们从Si.a连一条容量为1的边,f[i]=1i我们从i.bT连一条容量为1的边。并且每个点内部i.ai.b连一条容量为1的边。然后对于每个i,都要从i.b向所有满足f[j]+1=f[i]且a[j]>=a[i]j中的j.a都连一条容量为1的边。这样建完图之后,我们跑一遍最大流即可求出最多能取出多少个长度为maxl的不下降子序列。

      考虑正确性。首先把每个点拆成两个,内部容量为1,则可以保证每个点最多被选一次。Sf[i]=maxl的点连边,可以保证我们取出的起点一定是有解而且正确的。f[i]=1同理。如此以来,我们就能得出第二问的答案。

      第三问的话实际上就是在第二问的基础上加以改进。因为第一个元素和最后一个元素可以取多个,那么我们只需要去掉对于这两个元素的个数约束就可以了。所以S1n的边,1nT的边,内部的边,全部把容量改为无穷大就可以了。其余的和第二问没有区别。

     
      1 //It is made by jump~
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #include <set>
     13 #ifdef WIN32   
     14 #define OT "%I64d"
     15 #else
     16 #define OT "%lld"
     17 #endif
     18 using namespace std;
     19 typedef long long LL;
     20 const int MAXN = 520;
     21 const int MAXM = 500011;
     22 const int inf = (1<<30);
     23 int n,a[MAXN],f[MAXN];
     24 int b[MAXN],maxl;
     25 int S,T,ecnt,ans;
     26 int first[MAXN*2],deep[MAXN*2];
     27 queue<int>Q;
     28 struct edge{
     29     int to,next,f;
     30 }e[MAXM];
     31 
     32 inline int getint()
     33 {
     34        int w=0,q=0;
     35        char c=getchar();
     36        while((c<'0' || c>'9') && c!='-') c=getchar();
     37        if (c=='-')  q=1, c=getchar();
     38        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
     39        return q ? -w : w;
     40 }
     41 
     42 inline void link(int x,int y,int z){
     43     e[++ecnt].next=first[x]; first[x]=ecnt; e[ecnt].to=y; e[ecnt].f=z;
     44     e[++ecnt].next=first[y]; first[y]=ecnt; e[ecnt].to=x; e[ecnt].f=0;
     45 }
     46 
     47 inline int find(int x){
     48     int l=1,r=maxl; int mid,ji=-1;
     49     while(l<=r) {
     50     mid=(l+r)/2;
     51     if(b[mid]>=x) l=mid+1,ji=mid;
     52     else r=mid-1;
     53     }
     54     if(ji==-1) return 0;
     55     return ji;
     56 }
     57 
     58 inline void build(){//建图,S向f[i]=maxl的点连边,每个点拆成两个,i拆为i和i+n,f[i]=1的点向T
     59     S=2*n+1; T=S+1;  ecnt=1;
     60     for(int i=1;i<=n;i++) {
     61     link(i,i+n,1);
     62     if(f[i]==maxl) link(S,i,1);
     63     else if(f[i]==1) link(i+n,T,1);
     64     for(int j=i+1;j<=n;j++) {
     65         if(a[j]>=a[i] && f[j]+1==f[i]) link(i+n,j,1);
     66     }
     67     }
     68 }
     69 
     70 inline bool BFS(){
     71     while(!Q.empty()) Q.pop();
     72     memset(deep,0,sizeof(deep));
     73     Q.push(S); deep[S]=1;    
     74     while(!Q.empty()) {
     75     int u=Q.front(); Q.pop();
     76     for(int i=first[u];i;i=e[i].next) {
     77         int v=e[i].to;
     78         if(e[i].f && !deep[v]) deep[v]=deep[u]+1,Q.push(v);
     79     }
     80     }
     81     if(!deep[T]) return false;
     82     return true;
     83 }
     84 
     85 inline int maxflow(int x,int remain){
     86     if(x==T || remain==0) return remain;
     87     int flow=0,f;
     88     for(int i=first[x];i;i=e[i].next) {
     89     if(e[i].f && deep[e[i].to]==deep[x]+1) {
     90         int v=e[i].to;
     91         f=maxflow(v,min(remain,e[i].f));
     92         if(f) {
     93         flow+=f; e[i].f-=f; e[i^1].f+=f;
     94         remain-=f;
     95         if(remain==0) return flow;
     96         }else deep[v]=-1; 
     97     }
     98     }
     99     return flow;
    100 }
    101 
    102 inline void build_new(){
    103     memset(first,0,sizeof(first));
    104     S=2*n+1; T=S+1;  ecnt=1;
    105     for(int i=1;i<=n;i++) {
    106     if(i==1 || i==n) {
    107         link(i,i+n,inf);
    108         if(f[i]==maxl) link(S,i,inf);
    109         else if(f[i]==1) link(i+n,T,inf);
    110     }
    111     else{
    112         link(i,i+n,1);
    113         if(f[i]==maxl) link(S,i,1);
    114         else if(f[i]==1) link(i+n,T,1);
    115     }
    116     for(int j=i+1;j<=n;j++) {
    117         if(a[j]>=a[i] && f[j]+1==f[i]) link(i+n,j,1);
    118     }
    119     }
    120 }
    121 
    122 inline void work(){
    123     n=getint(); for(int i=1;i<=n;i++) a[i]=getint();
    124     for(int i=n;i>=1;i--) {
    125     f[i]=find(a[i])+1;
    126     if(b[f[i]]==0) b[f[i]]=a[i];
    127     else b[f[i]]=max(a[i],b[f[i]]);
    128     maxl=max(maxl,f[i]);
    129     }
    130     printf("%d
    ",maxl);
    131 
    132     build();
    133     while(BFS()) ans+=maxflow(S,inf);
    134     if(ans==0) ans=n;
    135     printf("%d
    ",ans);
    136 
    137     ans=0;
    138     build_new();
    139     while(BFS()) ans+=maxflow(S,inf);
    140     if(ans==0) ans=n;
    141     printf("%d
    ",ans);
    142 }
    143 
    144 int main()
    145 {
    146   work();
    147   return 0;
    148 }
    149  
     
  • 相关阅读:
    APS.NET MVC + EF (01)---Linq和Lambda表达式
    APS.NET MVC + EF (00)---C#基础
    Asp.net MVC 之ActionResult
    在ASP.NET MVC中加载部分视图的方法及差别
    Entity Framework Codefirst数据迁移
    Entity Framework Codefirst的配置步骤
    02:PostgreSQL Character Sets
    安装postgis,使用postgis导入shapefile的步骤总结
    WebGIS实现在线要素编辑之ArcGIS Server 发布Feature Service 过程解析
    DEM数据及其他数据下载
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5744266.html
Copyright © 2011-2022 走看看