zoukankan      html  css  js  c++  java
  • [cogs731] [网络流24题#6] 最长递增子序列 [网络流,最大流]

    【转hzwer】第一问是LIS,动态规划求解,第二问和第三问用网络最大流解决。首先动态规划求出F[i],表示以第i位为开头的最长上升序列的长度,求出最长上升序列长度K。1、把序列每位i拆成两个点<i.a>和<i.b>,从<i.a>到<i.b>连接一条容量为1的有向边。2、建立附加源S和汇T,如果序列第i位有F[i]=K,从S到<i.a>连接一条容量为1的有向边。3、如果F[i]=1,从<i.b>到T连接一条容量为1的有向边。4、如果j>i且A[i] < A[j]且F[j]+1=F[i],从<i.b>到<j.a>连接一条容量1的有向边。求网络最大流,就是第二问的结果。把边(<1.a>,<1.b>)(<N.a>,<N.b>)(S,<1.a>)(<N.b>,T)这四条边的容量修改为无穷大,再求一次网络最大流,就是第三问结果。利用动规求解网络流问题。

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <ctime>
    #include <queue>
    #include <stack>
    #include <vector>
    
    using namespace std;
    
    #define    Debug
    
    template<const int _n,const int _m>
    struct Edge
    {
        struct Edge_base { int    to,next,w; }e[_m]; int    cnt,p[_n];
        Edge() { clear(); }
        void    insert(const int x,const int y,const int z)
        { e[++cnt].to=y; e[cnt].next=p[x]; e[cnt].w=z; p[x]=cnt; return ; }
        int    start(const int x) { return p[x]; }
        void    clear() { cnt=1,memset(p,0,sizeof(p)); }
        Edge_base&    operator[](const int x) { return e[x]; }
    };
    
    Edge<11000,1100000>    e;
    int    Ans=0,tAns;
    int    n,a[5100],cur[11000],level[11000],SSS,TTT;
    int    f[11000];
    
    bool    Bfs(const int S)
    {
        int    i,t;
        queue<int>    Q;
        memset(level,0,sizeof(level));
        level[S]=1;
        Q.push(S);
        while(!Q.empty())
        {
            t=Q.front(),Q.pop();
            for(i=e.start(t);i;i=e[i].next)
            {
                if(!level[e[i].to] && e[i].w)
                {
                    level[e[i].to]=level[t]+1;
                    Q.push(e[i].to);
                }
            }
        }
        return level[TTT];
    }
    
    int    Dfs(const int S,const int bk)
    {
        if(S==TTT)return bk;
        int    rest=bk;
        for(int &i=cur[S];i;i=e[i].next)
        {
            if(level[e[i].to]==level[S]+1 && e[i].w)
            {
                int    flow=Dfs(e[i].to,min(rest,e[i].w));
                e[i].w-=flow;
                e[i^1].w+=flow;
                if((rest-=flow)<=0)break;
            }
        }
        if(rest==bk)level[S]=0;
        return bk-rest;
    }
    
    int    Dinic()
    {
        int    flow=0;
        while(Bfs(SSS))
        {
            memcpy(cur,e.p,sizeof(cur));
            flow+=Dfs(SSS,0x3f3f3f3f);
        }
        return flow;
    }
    
    void    Calc1()
    {
        int    i,j;
    
        for(i=1;i<=n;++i)
        {
            if(f[i]==1)e.insert(SSS,i,1),e.insert(i,SSS,0);
            if(f[i]==Ans)e.insert(i+n,TTT,1),e.insert(TTT,i+n,0);
            e.insert(i,i+n,1);
            e.insert(i+n,i,0);
        }
        for(i=1;i<=n;++i)
        {
            for(j=i+1;j<=n;++j)
            {
                if(a[j]>=a[i] && f[j]==f[i]+1)
                    e.insert(i+n,j,1),e.insert(j,i+n,0);
            }
        }
        printf("%d
    ",tAns=Dinic());
    }
    
    void    Calc2()
    {
        int    i,j;
        e.clear();
        for(i=1;i<=n;++i)
        {
            int    v=1;
            if(i==1 || i==n)v=0x3f3f3f3f;
            if(f[i]==1)e.insert(SSS,i,v),e.insert(i,SSS,0);
            if(f[i]==Ans)e.insert(i+n,TTT,v),e.insert(TTT,i+n,0);
            e.insert(i,i+n,v);
            e.insert(i+n,i,0);
        }
        for(i=1;i<=n;++i)
        {
            for(j=i+1;j<=n;++j)
            {
                if(a[j]>=a[i] && f[j]==f[i]+1)
                    e.insert(i+n,j,1),e.insert(j,i+n,0);
            }
        }
        int    temp=Dinic();
        if(temp>=0x3f3f3f3f)temp=tAns;
        printf("%d
    ",temp);
        return ;
    }
    
    
    int main()
    {
        freopen("alis.in","r",stdin);
        freopen("alis.out","w",stdout);
    
        int    i,j;
    
        scanf("%d",&n);
        for(i=1;i<=n;++i)scanf("%d",&a[i]);
    
        for(i=1;i<=n;++i)
        {
            f[i]=1;
            for(j=1;j<i;++j)
                if(a[j]<=a[i])f[i]=max(f[i],f[j]+1);
            Ans=max(Ans,f[i]);
        }
    
        printf("%d
    ",Ans);
    
        SSS=n<<1|1,TTT=SSS+1;
        Calc1();
        Calc2();
    
        return 0;
    }
  • 相关阅读:
    Java提高学习之Object(5)
    cmd命令。
    CacheView。
    快速界面:QML。
    抓包工具。
    打包安装程序。
    AS:加载新版本的SWF文件。
    as自定义菜单。
    as [Frame]元标签
    转载:Flash AS3.0 加载外部资源(图片,MP3,SWF)的两种方式
  • 原文地址:https://www.cnblogs.com/Gster/p/4996943.html
Copyright © 2011-2022 走看看