【Luogu】P2766最长不下降子序列问题(暴力网络流)

  题目链接

  水题qwq,数据都那么水。

  我要是出数据的人我就卡$n^3$建图。

  qwq。

  然而这么水的题我!居!然!没!有!1!A!!还!提!交!了!五!遍!!!

  md从现在开始要锻炼1A率了

  看我从今往后做完一道题之后至少检查TM十分钟

  可恶qwq。

  第一问$n^2$sbDP可解。然而你们知道我提交五遍TM是错在哪里了吗?????

  我TM就错在这个pj-,sb到不能再sb的sb暴力DP上!!!

  气死我了!!!

  关于第二问和第三问,先拆点再拆点qwq。

  先把每个点拆成入点和出点用来限制流量,然后把出点拆成s个点为的是跑最大流的时候统计比较方便。

  能跑到汇点就是一种方式,跑不到就说明没有那么长的最长不下降子序列。

  第三问暴力修改边容量再跑一遍即可。

  qwqqqqqqqqq我网络流都没写错栽在一个入门DP上

  qwqqqqqq

  

#include<cstdio>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#define maxm 200010
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch==‘-‘)    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-‘0‘;
        ch=getchar();
    }
    return num*f;
}

int n,m;
int q[100010];
int s[100010];
int ne[510][510],tot[510];
int Start,End;
inline int count(int i){    return i&1?i+1:i-1;    }

struct Edge{
    int next,to,val;
}edge[maxm*4];
int head[maxm],num;
inline void addedge(int from,int to,int val){
    edge[++num]=(Edge){head[from],to,val};
    head[from]=num;
}
inline void add(int from,int to,int val){
    addedge(from,to,val);
    addedge(to,from,0);
}

bool vis[maxm];
int dfn[maxm];
int list[maxm];

bool bfs(){
    memset(vis,0,sizeof(vis));    vis[Start]=1;    dfn[Start]=1;
    queue<int>q;    q.push(Start);
    while(!q.empty()){
        int from=q.front();q.pop();
        for(int i=head[from];i;i=edge[i].next){
            int to=edge[i].to;
            if(edge[i].val==0||vis[to])    continue;
            vis[to]=1;    dfn[to]=dfn[from]+1;
            q.push(to);
        }
    }
    return vis[End];
}

int dfs(int x,int val){
    if(x==End||val==0)    return val;
    int flow=0;    vis[x]=1;
    for(int &i=list[x];i;i=edge[i].next){
        int to=edge[i].to;
        if(vis[to]||edge[i].val==0||dfn[to]!=dfn[x]+1)    continue;
        int now=dfs(to,min(val,edge[i].val));
        val-=now;    flow+=now;    edge[i].val-=now;    edge[count(i)].val+=now;
        if(val<=0)    break;
    }
    if(val!=flow)    dfn[x]=-1;
    return flow;
}

int maxflow(){
    int ans=0;
    while(bfs()){
        memset(vis,0,sizeof(vis));
        for(int i=Start;i<=End;++i)    list[i]=head[i];
        int now=dfs(Start,0x7fffffff);
        if(!now)    break;
        ans+=now;
    }
    return ans;
}

int main(){
    int n=read();
    for(int i=1;i<=n;++i){
        q[i]=read();s[i]=1;
    }
    m=1;
    for(int i=n-1;i>=1;--i){
        for(int j=i+1;j<=n;++j){
            if(q[i]>q[j])    continue;
            if(s[i]<s[j]+1)    s[i]=s[j]+1;
            if(m<s[i])    m=s[i];
        }
    }
    printf("%d\n",m);
    End=(m+1)*n+n+1;
    for(int i=1;i<=n;++i){
        add(Start,i,0x7fffffff);
        add(i,i+n,1);
        add(m*n+i,End,1);
        for(int j=i+1;j<=n;++j){
            if(q[i]>q[j])    continue;
            for(register int k=1;k<m;++k)    add(k*n+i,(k+1)*n+j,1);
        }
    }
    int ans=maxflow();
    printf("%d\n",ans);
    int ret=1;
    for(int j=head[ret];j;j=edge[j].next){
        int to=edge[j].to;
        if(to<ret)    continue;
        edge[j].val+=1234567;
    }
    /*for(int j=head[1];j;j=edge[j].next){
        int to=edge[j].to;
        edge[j].val+=1234567;
    }*/
    ret=m*n+n;
    for(int j=head[ret];j;j=edge[j].next){
        int to=edge[j].to;
        if(to!=End)    continue;
        edge[j].val+=1234567;
    }
    printf("%d",ans+maxflow());
    return 0;
}

原文地址:https://www.cnblogs.com/cellular-automaton/p/8270123.html

时间: 2024-10-14 18:58:24

【Luogu】P2766最长不下降子序列问题(暴力网络流)的相关文章

P2766 最长不下降子序列问题 网络流

link:https://www.luogu.org/problemnew/show/P2766 题意 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列. 设计有效算法完成(1)(2)(3)提出的计算任务. 思路 题解来自网络流24题: [问题分析] 第一问是LIS,动态规划求解,第二问和第三问用网络最

P2766 最长不下降子序列问题

\(\color{#0066ff}{题目描述}\) ?问题描述: 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列. ?编程任务: 设计有效算法完成(1)(2)(3)提出的计算任务. \(\color{#0066ff}{输入格式}\) 第1 行有1个正整数n,表示给定序列的长度.接下来的1 行有n个正整

网络流24题之最长不下降子序列问题

P2766 最长不下降子序列问题 题目描述 ?问题描述: 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列. ?编程任务: 设计有效算法完成(1)(2)(3)提出的计算任务. n<=500 输入输出格式 输入格式: 第1 行有1个正整数n,表示给定序列的长度.接下来的1 行有n个正整数n:x1, ...

[网络流24题]最长不下降子序列问题

[luogu 2766] 最长不下降子序列问题 传送门 第一问: \(O(n^2)\) 的DP求LIS 为了下面叙述方便,我们将DP过程讲一遍 子状态:dp[i]表示以a[i]结尾的LIS长度 初始条件:dp[i]=1 状态转移方程:\(dp[i]=dp[j]+1(j<i,a[j]\leq a[i])\) 第二问: 我们发现若a[j]加上a[i]可以构成一个不下降子序列,则\(j<i,a[j] \leq a[i]\) 又发现每个元素只能在一个序列中,考虑拆点 建图方法: 原点S=0,T=2n+

P2766 [网络流24题]最长不下降子序列问题

ha~ ?问题描述: 给定正整数序列$x_1,...,x_n$ .$n<=500$ 求(1)计算其最长不下降子序列的长度$s$. (2)计算从给定的序列中最多可取出多少个长度为$s$的不下降子序列. (3)如果允许在取出的序列中多次使用$x_1$和$x_n$,则从给定序列中最多可取出多少个长度为$s$的不下降子序列. (1)暴力n方解决 (2)建分层图,把图每个顶点i按照F[i]的不同分为若干层,这样图中从S出发到T的任何一条路径都是一个满足条件的最长不下降子序列.由 S 向所有$ f_i =

洛谷2766:[网络流24题]最长不下降子序列问题——题解

https://www.luogu.org/problemnew/show/P2766 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列. 第一问用dp求解不多说了. 考虑第二问,每个数只用一次很好办,把数拆点(入点和出点)中间连边权为1的边即可. 现在的问题就是如何让它能够跑满s个点. 我们设dp[i

swust oj 585--倒金字塔(LIS最长不下降子序列)

题目链接:http://acm.swust.edu.cn/problem/585/ Time limit(ms): 3000 Memory limit(kb): 65535 SWUST国的一支科学考察队到达了举世闻名的古埃及金字塔. 关于金字塔的建造一直是一个未解之谜, 有着“西方史学之父”之称的希罗多德认为,金字塔的建造是人力和牲畜,花费20 年时间从西奈半岛挖掘天然的石头运送到埃及堆砌而成.也有不少人认为是外星人修建的.人们发现胡夫金字塔的经线把地球分成东.西两个半球,它们的陆地面积是相等的

最长不下降子序列nlogn算法详解

今天花了很长时间终于弄懂了这个算法……毕竟找一个好的讲解真的太难了,所以励志我要自己写一个好的讲解QAQ 这篇文章是在懂了这个问题n^2解决方案的基础上学习. 解决的问题:给定一个序列,求最长不下降子序列的长度(nlogn的算法没法求出具体的序列是什么) 定义:a[1..n]为原始序列,d[k]表示长度为k的不下降子序列末尾元素的最小值,len表示当前已知的最长子序列的长度. 初始化:d[1]=a[1]; len=1; (0个元素的时候特判一下) 现在我们已知最长的不下降子序列长度为1,末尾元素

tyvj 1049 最长不下降子序列 n^2/nlogn

P1049 最长不下降子序列 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 求最长不下降子序列的长度 输入格式 第一行为n,表示n个数第二行n个数 输出格式 最长不下降子序列的长度 测试样例1 输入 3 1 2 3 输出 3 备注 N小于5000for each num <=maxint 题意:中文题意 题解:不下降也就是>= n^n  dp[i] 表示前i个数的最长不下降子序列的长度 1 /*****************************