zoukankan      html  css  js  c++  java
  • 【网络流24题】最长递增子序列

    Description

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

    Input

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

    Output

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

    Sample Input

    4
    3 6 2 5

    Sample Output

    2
    2
    3

    Hint

    Source

    网络流
    最多不相交路径,网络最大流

    思路{

      第一问DP求解

      第二问,第三问网络流即可{

        虚拟源汇点,从sf[i]=1的连容量为1,中间转移的容量为1f[i]max的连向汇点,容量为1,最大流即可。

        虚拟源汇点,从sf[i]=1的连容量为INF,中间转移的容量为1f[i]max的连向汇点,容量为INF,最大流即可。

        记(wei)得(suo)特判一下

      }

    }

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<ctime>
    #include<cmath>
    #include<map>
    #include<set>
    #define MAXX 502
    #define MAXM 502*502+1001
    #define INF 9999999
    using namespace std;
    
    struct se{
      int nxt,to,c;
    }e[MAXM*4];
    
    int n,m,a[MAXX+1],f[MAXX+1],tot,head[MAXX+1],deep[MAXX+1],all;
     
    void add(int from,int to,int w){
      e[tot].nxt=head[from];
      e[tot].to=to;
      e[tot].c=w;
      head[from]=tot++;
    }
    void ADD(int from,int to,int w){
      add(from,to,w);
      add(to,from,0);
    }
    void DP(){
      f[1]=1;
      for(int i=2;i<=n;++i){
        for(int j=i-1;j;j--){
          if(f[j]>f[i]&&a[j]<=a[i])
        f[i]=f[j];
        }f[i]++;
      }for(int i=1;i<=n;++i)all=max(all,f[i]);
      printf("%d
    ",all);
    }
    bool BFS(int s,int t){
      queue<int>que;
      while(!que.empty())que.pop();
      for(int i=1;i<=n+2;++i)deep[i]=0;
      que.push(s),deep[s]=1;
      while(!que.empty()){
        int u=que.front();
        for(int i=head[u];i!=-1;i=e[i].nxt)if(!deep[e[i].to]&&e[i].c){
        int v=e[i].to;
        deep[v]=deep[u]+1;
        que.push(v);
        if(v==t)return 1;
          }
        que.pop();
      }return 0;
    }
    int dinic(int s,int t,int T){
      if(s==t)return T;int tag=0;
      for(int i=head[s];i!=-1;i=e[i].nxt)if(e[i].c&&deep[e[i].to]==deep[s]+1){
          int d=dinic(e[i].to,t,min(T,e[i].c));
          e[i].c-=d,e[i^1].c+=d;tag+=d;
          if(tag==T)return tag;
        }return tag;
    }
    void flow1(){
      for(int i=1;i<=n;++i)if(f[i]==1)ADD(0,i,1);
      for(int j=2;j<=n;++j){
        if(f[j]==all)ADD(j,n+1,1);
        for(int i=1;i<j;++i)
          if((f[i]+1==f[j])&&a[i]<=a[j])
        ADD(i,j,1);
      }
      int ans=0;
      while(BFS(0,n+1))ans+=dinic(0,n+1,INF);
      if(all!=1)
      printf("%d
    ",ans);
      else cout<<ans+1<<'
    ';
    }
    void flow2(){
      memset(e,0,sizeof(e));tot=0;
      memset(head,-1,sizeof(head));
      for(int i=1;i<=n;++i)if(f[i]==1)ADD(0,i,INF);
      for(int j=2;j<=n;++j){
        if(f[j]==all)ADD(j,n+1,INF);
        for(int i=1;i<j;++i)
          if((f[i]+1==f[j])&&a[i]<=a[j])
        ADD(i,j,1);
      }
      int ans=0;
      while(BFS(0,n+1))ans+=dinic(0,n+1,INF);
      printf("%d
    ",ans);
    }
    int main(){
      memset(head,-1,sizeof(head));
      scanf("%d",&n);
      for(int i=1;i<=n;++i)scanf("%d",&a[i]);
      DP();
      if(all!=1)flow1(),flow2();
      if(all==1)flow1(),flow1();
      return 0;
    }
  • 相关阅读:
    poj 3666 Making the Grade
    poj 3186 Treats for the Cows (区间dp)
    hdu 1074 Doing Homework(状压)
    CodeForces 489C Given Length and Sum of Digits...
    CodeForces 163A Substring and Subsequence
    CodeForces 366C Dima and Salad
    CodeForces 180C Letter
    CodeForces
    hdu 2859 Phalanx
    socket接收大数据流
  • 原文地址:https://www.cnblogs.com/zzmmm/p/6658585.html
Copyright © 2011-2022 走看看