zoukankan      html  css  js  c++  java
  • Luogu 2766

    题目链接:https://www.luogu.org/problemnew/show/P2766

    题解(大量参考https://blog.csdn.net/ZscDst/article/details/82423342):

    第一问,可以用DP求解,用 $f[i]$ 表示以 $a[i]$ 为结尾的最长不减子序列的长度,DP时间复杂度 $O(n^2)$,假设求得长度为 $len$。

    第二问我们可以用网络流来求解:

    1、由于每个点只能被选一次,所以拆点,控制每个数只能选一次。

    2、源点往所有 $f[i]=1$ 的点连一条边权为 $1$ 的边,所有 $f[i]=len$ 的点往汇点连一条边权为 $1$ 的边。

    3、如果 j 点是由 i 点转移得到的(即f[i]+1==f[j] && a[i] <= a[j]),那么 i+n 往 j 连一条边权为1的边。

    第三问:

    $x[1]$ 和 $x[n]$ 可以使用多次,首先 $x[1],x[n]$ 拆出来的两个点之间的容量需要修改。

    同时,此题中必然有一条边从源点连向 $x[1]$,所以这条边的容量也要修改。$x[n]$ 不一定是汇点,若 $x[n]$ 是汇点,那么 $x[n]$ 到汇点的边的容量也要修改。

    如果重新构图去跑可能会超时,我们知道网络流是可以继续在残量网络中跑的,所以我们直接再添加新边,再继续跑网络流,累加到第二问的答案上,即为第三问的答案。

    AC代码:

    #include<bits/stdc++.h>
    #define I(x) x
    #define O(x) (n+x)
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int maxn=505;
    
    int n,x[maxn];
    int f[maxn];
    
    struct Edge{
        int u,v,c,f;
    };
    struct Dinic
    {
        static const int SIZE=2*maxn;
        int s,t; //源点汇点
        vector<Edge> E;
        vector<int> G[SIZE];
        void init(int l,int r)
        {
            E.clear();
            for(int i=l;i<=r;i++) G[i].clear();
        }
        void addedge(int from,int to,int cap)
        {
            E.push_back((Edge){from,to,cap,0});
            E.push_back((Edge){to,from,0,0});
            G[from].push_back(E.size()-2);
            G[to].push_back(E.size()-1);
        }
        int dist[SIZE],vis[SIZE];
        queue<int> q;
        bool bfs() //在残量网络上构造分层图
        {
            memset(vis,0,sizeof(vis));
            while(!q.empty()) q.pop();
            q.push(s);
            dist[s]=0;
            vis[s]=1;
            while(!q.empty())
            {
                int now=q.front(); q.pop();
                for(int i=0;i<G[now].size();i++)
                {
                    Edge& e=E[G[now][i]]; int nxt=e.v;
                    if(!vis[nxt] && e.c>e.f)
                    {
                        dist[nxt]=dist[now]+1;
                        q.push(nxt);
                        vis[nxt]=1;
                    }
                }
            }
            return vis[t];
        }
        int dfs(int now,int flow)
        {
            if(now==t || flow==0) return flow;
            int rest=flow,k;
            for(int i=0;rest>0 && i<G[now].size();i++)
            {
                Edge &e=E[G[now][i]]; int nxt=e.v;
                if(e.c>e.f && dist[nxt]==dist[now]+1)
                {
                    k=dfs(nxt,min(rest,e.c-e.f));
                    if(!k) dist[nxt]=0; //剪枝,去掉增广完毕的点
                    e.f+=k; E[G[now][i]^1].f-=k;
                    rest-=k;
                }
            }
            return flow-rest;
        }
        int mf; //存储最大流
        int maxflow()
        {
            mf=0;
            int flow=0;
            while(bfs()) while(flow=dfs(s,INF)) mf+=flow;
            return mf;
        }
    }dinic;
    
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++) scanf("%d",&x[i]);
    
        int len=1;
        dinic.init(dinic.s=0,dinic.t=2*n+1);
        for(int i=1;i<=n;i++)
        {
            dinic.addedge(I(i),O(i),1);
    
            f[i]=1;
            for(int j=1;j<i;j++)
                if(x[j]<=x[i]) f[i]=max(f[i],f[j]+1);
            len=max(len,f[i]);
    
            if(f[i]==1) dinic.addedge(dinic.s,I(i),1);
            else
            {
                for(int j=1;j<i;j++)
                    if(x[j]<=x[i] && f[j]+1==f[i]) dinic.addedge(O(j),I(i),1);
            }
        }
        cout<<len<<endl;
    
        for(int i=1;i<=n;i++)
            if(f[i]==len) dinic.addedge(O(i),dinic.t,1);
    
        int ans=dinic.maxflow();
        cout<<ans<<endl;
    
    
        dinic.addedge(dinic.s,I(1),INF), dinic.addedge(I(1),O(1),INF);
        dinic.addedge(I(n),O(n),INF);
        if(f[n]==len) dinic.addedge(O(n),dinic.t,INF);
    
        cout<<ans+dinic.maxflow()<<endl;
    }
  • 相关阅读:
    java.lang.UnsupportedOperationException: Not supported by BasicDataSource
    c# seo 百度sitemap书写
    c# 泛型原理(旧)
    apache 服务器配置常用知识点合集
    sass 基本常识
    c# TryParse
    webpack 配置热更新
    c# ref和out 详解
    IIS applicationHost.config 查找历史
    c# webapi 自定义返回数据
  • 原文地址:https://www.cnblogs.com/dilthey/p/10711434.html
Copyright © 2011-2022 走看看