首页 > 代码库 > 【网络流24题】 最长递增子序列问题

【网络流24题】 最长递增子序列问题

(题目复制自洛谷)

题目描述

给定正整数序列x1,...,xn 。

(1)计算其最长递增子序列的长度s。

(2)计算从给定的序列中最多可取出多少个长度为s的递增子序列。

(3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的递增子序列。

编程任务:

设计有效算法完成(1)(2)(3)提出的计算任务。

 

输入输出格式

输入格式:

第1 行有1个正整数n,表示给定序列的长度。接下来的1 行有n个正整数n:x1, ..., xn。

 

输出格式:

第1 行是最长递增子序列的长度s。第2行是可取出的长度为s 的递增子序列个数。第3行是允许在取出的序列中多次使用x1和xn时可取出的长度为s 的递增子序列个数。

 

输入输出样例

输入样例#1:
4
3 6 2 5
输出样例#1:
2
2
3


以前做过,再复习一下网络流。
  1 program alis(input,output);
  2 const
  3   inf=123456789;
  4 type
  5   etype=record
  6      t,c,next,rev:longint;
  7   end;
  8 var
  9   a,d,cur:array[-550..550]of longint;
 10   e:array[0..1000010]of etype;
 11   f,x:array[0..500]of longint;
 12   q:array[0..1010]of longint;
 13   n,i,j,ans,h,t,cnt,r:longint;
 14 function max(a,b:longint):longint;
 15 begin
 16    if a>b then exit(a) else exit(b);
 17 end;
 18 function min(a,b:longint):longint;
 19 begin
 20    if a<b then exit(a) else exit(b);
 21 end;
 22 procedure ins(x,y,c:longint);
 23 begin
 24    inc(cnt);e[cnt].t:=y;e[cnt].c:=c;e[cnt].next:=a[x];a[x]:=cnt;
 25 end;
 26 procedure add(x,y,c:longint);
 27 begin
 28    ins(x,y,c);e[cnt].rev:=cnt+1;ins(y,x,0);e[cnt].rev:=cnt-1;
 29 end;
 30 procedure bfs;
 31 begin
 32    for i:=-n to n+1 do d[i]:=-1;
 33    h:=0;t:=1;q[1]:=0;d[0]:=0;
 34    while h<t do
 35       begin
 36          inc(h);i:=a[q[h]];
 37          while i<>0 do
 38             begin
 39                if (e[i].c>0) and (d[e[i].t]=-1) then
 40                   begin
 41                      d[e[i].t]:=d[q[h]]+1;
 42                      inc(t);q[t]:=e[i].t;
 43                   end;
 44                i:=e[i].next;
 45             end;
 46       end;
 47 end;
 48 function dfs(k,f:longint):longint;
 49 var
 50   ans,r,i:longint;
 51 begin
 52    if (k=n+1) or (f=0) then exit(f);
 53    ans:=0;i:=cur[k];
 54    while i<>0 do
 55       begin
 56          if (d[e[i].t]=d[k]+1) and (e[i].c>0) then
 57             begin
 58                r:=dfs(e[i].t,min(f,e[i].c));
 59                dec(e[i].c,r);inc(e[e[i].rev].c,r);
 60                inc(ans,r);dec(f,r);
 61                if f=0 then break;
 62             end;
 63          i:=e[i].next;
 64          cur[k]:=i;
 65       end;
 66    if f>0 then d[k]:=-1;
 67    exit(ans);
 68 end;
 69 function maxflow:longint;
 70 var
 71   ans:longint;
 72 begin
 73    ans:=0;
 74    while true do
 75       begin
 76          bfs;
 77          if d[n+1]=-1 then break;
 78          for i:=-n to n+1 do cur[i]:=a[i];
 79          ans:=ans+dfs(0,inf);
 80       end;
 81    exit(ans);
 82 end;
 83 begin
 84    assign(input,alis.in);assign(output,alis.out);reset(input);rewrite(output);
 85    readln(n);
 86    for i:=1 to n do read(x[i]);
 87    ans:=0;
 88    for i:=1 to n do
 89       begin
 90          f[i]:=1;
 91          for j:=1 to i-1 do
 92             if x[j]<=x[i] then f[i]:=max(f[i],f[j]+1);
 93          ans:=max(ans,f[i]);
 94       end;
 95    writeln(ans);
 96    fillchar(a,sizeof(a),0);cnt:=0;
 97    for i:=1 to n do add(-i,i,1);
 98    for i:=1 to n do if f[i]=1 then add(0,-i,1);
 99    for i:=2 to n do for j:=1 to i-1 do if (f[i]=f[j]+1) and (x[j]<=x[i]) then add(j,-i,1);
100    for i:=1 to n do if f[i]=ans then add(i,n+1,1);
101    r:=maxflow;writeln(r);
102    add(0,1,inf);if f[n]=ans then add(-n,n+1,inf);
103    writeln(r+maxflow);
104    close(input);close(output);
105 end.

 



【网络流24题】 最长递增子序列问题