首页 > 代码库 > 【网络流24题】最长递增子序列
【网络流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求解
第二问,第三问网络流即可{
虚拟源汇点,从s向f[i]=1的连容量为1,中间转移的容量为1,f[i]为max的连向汇点,容量为1,最大流即可。
虚拟源汇点,从s向f[i]=1的连容量为INF,中间转移的容量为1,f[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\n",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\n",ans); else cout<<ans+1<<‘\n‘; } 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\n",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; }
【网络流24题】最长递增子序列
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。