1. 程式人生 > >[網絡流24題]最長遞增子序列問題 最大流

[網絡流24題]最長遞增子序列問題 最大流

size 個數 clu 編程 input num pac ros ini

Description

給定正整數序列x1 ,... , xn 。 (1)計算其最長遞增子序列的長度s。(嚴格遞增) (2)計算從給定的序列中最多可取出多少個長度為s的遞增子序列。 (3)如果允許在取出的序列中多次使用x1和xn,則從給定序列中最多可取出多少個長 度為s的遞增子序列。 編程任務: 設計有效算法完成(1)(2)(3)提出的計算任務。

Input

由文件input.txt提供輸入數據。文件第1 行有1個正整數n(n<400),表示給定序列的長度。接 下來的1 行有n個正整數 x1 , ... , xn。

Output

程序運行結束時,將任務(1)(2)(3)的解答輸出到文件output.txt中。第1 行是最長 遞增子序列的長度s。第2行是可取出的長度為s 的遞增子序列個數。第3行是允許在取出 的序列中多次使用x1和xn時可取出的長度為s 的遞增子序列個數。

Sample Input

4 3 6 2 5

Sample Output

2 2 3 題解: 1.第一問直接DP 2.拆點,(i,i+n,1). if(F[i]==ans)init(i+n,T,1); if(F[i]==1)init(S,i,1). 3.把S-i i-i+n n+n-T n-n+n的容量改為正無窮即可
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1005,INF=1999999999
; int gi(){ int str=0;char ch=getchar(); while(ch>9||ch<0)ch=getchar(); while(ch>=0 && ch<=9)str=str*10+ch-48,ch=getchar(); return str; } int n,s[N],F[N],ans,S=0,T; int head[N],num=1; struct Lin{ int next,to,dis; }a[N*N*4]; void init(int x,int y,int z){ a[
++num].next=head[x]; a[num].to=y; a[num].dis=z; head[x]=num; a[++num].next=head[y]; a[num].to=x; a[num].dis=0; head[y]=num; } int dep[N],q[N]; bool bfs() { memset(dep,0,sizeof(dep)); int x,u,t=0,sum=1; dep[S]=1;q[1]=S; while(t!=sum) { x=q[++t]; for(int i=head[x];i;i=a[i].next){ u=a[i].to; if(a[i].dis<=0 || dep[u])continue; dep[u]=dep[x]+1;q[++sum]=u; } } return dep[T]; } int dfs(int x,int flow) { if(x==T || !flow)return flow; int u,tmp,sum=0; for(int i=head[x];i;i=a[i].next){ u=a[i].to; if(a[i].dis<=0 || dep[u]!=dep[x]+1)continue; tmp=dfs(u,flow<a[i].dis?flow:a[i].dis); a[i].dis-=tmp;a[i^1].dis+=tmp; flow-=tmp;sum+=tmp; if(!flow)break; } return sum; } int maxflow() { int tot=0,tmp; while(bfs()){ tmp=dfs(S,INF); while(tmp)tot+=tmp,tmp=dfs(S,INF); } return tot; } void Clear(){ memset(head,0,sizeof(head)); num=1; } int main() { n=gi();T=(n<<1)+1; for(int i=1;i<=n;i++)s[i]=gi(),F[i]=1; for(int i=1;i<=n;i++) { for(int j=1;j<i;j++)if(s[i]>s[j] && F[j]+1>F[i])F[i]=F[j]+1; if(F[i]>ans)ans=F[i]; } printf("%d\n",ans); for(int i=1;i<=n;i++) { init(i,i+n,1); if(F[i]==ans)init(i+n,T,1); if(F[i]==1)init(S,i,1); for(int j=1;j<i;j++) { if(s[i]>s[j] && F[j]+1==F[i])init(j+n,i,1); } } printf("%d\n",maxflow()); Clear(); for(int i=1;i<=n;i++) { init(i,i+n,1); if(F[i]==ans)init(i+n,T,1); if(F[i]==1)init(S,i,1); for(int j=1;j<i;j++) { if(s[i]>s[j] && F[j]+1==F[i])init(j+n,i,1); } } if(F[n]==ans)init(n+n,T,INF); init(1,1+n,INF);init(S,1,INF);init(n,n+n,INF); printf("%d",maxflow()); return 0; }

[網絡流24題]最長遞增子序列問題 最大流