zoukankan      html  css  js  c++  java
  • 【网络流24题】最长不下降子序列问题

    题目描述

    «问题描述:

    给定正整数序列x1,...,xn 。

    (1)计算其最长不下降子序列的长度s。

    (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列。

    (3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列。

    «编程任务:

    设计有效算法完成(1)(2)(3)提出的计算任务。

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    4
    3 6 2 5
    输出样例#1: 复制
    2
    2
    3

    说明

    nle 500n500


    这里我们先说明下题意:

    第二问里用过的元素不能再用,即取出的最多的不重叠的最长不下降子序列数量

    而第3问里,x1,xn可以重复用,但是出现过一次的序列不能再出现

    搞明白他要什么了之后就可以考虑构图了

    针对每个数智能用一次的限制,我们可以让i裂成$i$和$i'$

    从$i$到$i'$连一条1的边,就可以保证只用一次

    接下来我们考虑如何在各个点之间连边

    在第一问时我们处理出$f[i]$,从i出发所能接出的最长序列

    不难发现,无论拿出的时哪几个序列,如果要充分利用的话,$i$必然向$f[j]==f[i]-1$的$j$连边

    所以我们对于每个$i'$,找到所有能接在它后面且$f[j]==f[i]-1$的$j$,连$i'->j$为1

    最后对于所有$f[i]==s$的连$S-inf->i$,$f[i]==1$的连$i'-inf->T$

    至于为什么是inf嘛。。是为了方便1和n,当然这里可以分别处理吧(懒得想了

     1 #include<bits/stdc++.h>
     2 #define N 2005
     3 #define M 300000
     4 #define INF (1<<30)
     5 using namespace std;
     6 int h[N],to[M],nxt[M],fl[M],etop;
     7 int S=0,T=2000,n,x[505],f[505];
     8 void add(int u,int v,int w){
     9     //printf("%d %d %d
    ",u,v,w);
    10     to[etop]=v,nxt[etop]=h[u],fl[etop]=w,h[u]=etop++;
    11     to[etop]=u,nxt[etop]=h[v],fl[etop]=0,h[v]=etop++;
    12 }
    13 queue<int>q;
    14 int lev[N];
    15 inline bool bfs(){
    16     memset(lev,-1,sizeof(lev));
    17     lev[S]=0;q.push(S);
    18     while(!q.empty()){
    19         int u=q.front();q.pop();
    20         for(int k=h[u];~k;k=nxt[k]){
    21             int v=to[k];
    22             if(lev[v]==-1&&fl[k]){
    23                 lev[v]=lev[u]+1;
    24                 q.push(v);
    25             }
    26         }
    27     }
    28     return lev[T]!=-1;
    29 }
    30 int dfs(int u,int t,int left){
    31     if(u==t)return left;
    32     for(int k=h[u];~k;k=nxt[k]){
    33         int v=to[k];
    34         if(lev[v]==lev[u]+1&&fl[k]){
    35             int d=dfs(v,t,min(left,fl[k]));
    36             if(d){
    37                 fl[k]-=d;
    38                 fl[k^1]+=d;
    39                 return d;
    40             }
    41         }
    42     }
    43     return 0;
    44 }
    45 int dinic(){
    46     int flow=0,f;
    47     while(bfs()){
    48         while(f=dfs(S,T,INF))flow+=f;
    49     }
    50     return flow;
    51 }
    52 int s;
    53 void pre(){
    54     for(int i=n;i>=1;i--){
    55         for(int j=i+1;j<=n;j++)
    56         if(x[i]<=x[j])f[i]=max(f[i],f[j]);
    57         f[i]++;
    58         s=max(s,f[i]);
    59     }
    60 }
    61 int main(){
    62     scanf("%d",&n);
    63     for(int i=1;i<=n;i++)scanf("%d",&x[i]);
    64     pre();
    65     printf("%d
    ",s);
    66     if(s==1){
    67         printf("%d
    %d",n,n);
    68         return 0;
    69     }
    70     memset(h,-1,sizeof(h));
    71     for(int i=1;i<=n;i++){
    72         add(i<<1,i<<1|1,1);
    73         for(int j=i+1;j<=n;j++)
    74         if(f[i]==f[j]+1&&x[i]<=x[j])
    75         add(i<<1|1,j<<1,1);
    76         if(f[i]==1)add(i<<1|1,T,INF);
    77         if(f[i]==s)add(S,i<<1,INF);
    78     }
    79     printf("%d
    ",dinic());
    80     memset(h,-1,sizeof(h));
    81     etop=0;
    82     for(int i=1;i<=n;i++){
    83         if(i==1||i==n)add(i<<1,i<<1|1,INF);
    84         else add(i<<1,i<<1|1,1);
    85         for(int j=i+1;j<=n;j++)
    86         if(f[i]==f[j]+1&&x[i]<=x[j])
    87         add(i<<1|1,j<<1,1);
    88         if(f[i]==1)add(i<<1|1,T,INF);
    89         if(f[i]==s)add(S,i<<1,INF);
    90     }
    91     printf("%d
    ",dinic());
    92     return 0;
    93 }
    94 /*
    95 6
    96 4 7 1 6 4 3
    97 */
    View Code

    当然如果你也这样连边,别忘了特判坑爹的s==1,不然会出正无穷的。。。

  • 相关阅读:
    Ubuntu adb device
    ubuntu系统下创建软件桌面快捷方式
    Ubuntu 配置java环境变量
    Ubuntu 12.04 安装Chrome步骤
    java和php中static+final+synchronized 总结
    Sensor Hub 初探
    Ionic+PhoneGap+ Cordova
    Ionic初探 + 混合app的尝试
    ubuntu+dpkg+apt-get+aptitude 区别
    ubuntu下桌面系统及切换gdm+kdm+lightdm
  • 原文地址:https://www.cnblogs.com/2017SSY/p/10847951.html
Copyright © 2011-2022 走看看