zoukankan      html  css  js  c++  java
  • [网络流24题] 最长递增子序列

    731. [网络流24题] 最长递增子序列

    ★★★☆   输入文件:alis.in   输出文件:alis.out   简单对比
    时间限制:1 s   内存限制:128 MB


    «问题描述:
    给定正整数序列x1,..., xn。
    (1)计算其最长递增子序列的长度s。
    (2)计算从给定的序列中最多可取出多少个长度为s的递增子序列。
    (3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长
    度为s的递增子序列。

    注意:这里的最长递增子序列即最长不下降子序列!!!
    «编程任务:
    设计有效算法完成(1)(2)(3)提出的计算任务。
    «数据输入:
    由文件alis.in提供输入数据。文件第1 行有1个正整数n(n<=500),表示给定序列的长度。接
    下来的1 行有n个正整数x1,..., xn。
    «结果输出:
    程序运行结束时,将任务(1)(2)(3)的解答输出到文件alis.out中。第1 行是最长
    递增子序列的长度s。第2行是可取出的长度为s 的递增子序列个数。第3行是允许在取出
    的序列中多次使用x1和xn时可取出的长度为s 的递增子序列个数。
    输入文件示例 输出文件示例
    alis.in
    4

    3 6 2 5

    alis.out

    2
    2
    3

    【问题分析】

    第一问是LIS,动态规划求解,第二问和第三问用网络最大流解决。

    【建模方法】

    首先动态规划求出F[i],表示以第i位为开头的最长上升序列的长度,求出最长上升序列长度K。

    1、把序列每位i拆成两个点<i.a>和<i.b>,从<i.a>到<i.b>连接一条容量为1的有向边。
    2、建立附加源S和汇T,如果序列第i位有F[i]=K,从S到<i.a>连接一条容量为1的有向边。
    3、如果F[i]=1,从<i.b>到T连接一条容量为1的有向边。
    4、如果j>i且A[i] < A[j]且F[j]+1=F[i],从<i.b>到<j.a>连接一条容量为1的有向边。

    求网络最大流,就是第二问的结果。把边(<1.a>,<1.b>)(<N.a>,<N.b>)(S,<1.a>)(<N.b>,T)这四条边的容量修改为无穷大,再求一次网络最大流,就是第三问结果。

    【建模分析】

    上述建模方法是应用了一种分层图的思想,把图每个顶点i按照F[i]的不同分为了若干层,这样图中从S出发到T的任何一条路径都是一个满足条件的最长上升子序列。由于序列中每个点要不可重复地取出,需要把每个点拆分成两个点。单位网络的最大流就是增广路的条数,所以最大流量就是第二问结果。第三问特殊地要求x1和xn可以重复使用,只需取消这两个点相关边的流量限制,求网络最大流即可。

    转载自hzwer

    ps:任务3若能取出无限多的序列,则输出任务2的答案 

    1. //数据略坑
    2. #include<cstdio>
    3. #include<cstring>
    4. #include<algorithm>
    5. #define setfile(name) freopen(#name".in","r",stdin);freopen(#name".out","w",stdout);
    6. using namespace std;
    7. const int N=1005;
    8. const int inf=1e9;
    9. struct edge{int v,cap,next;}e[N*N*2];int tot=1,head[N];
    10. int n,S,T,K,ans,a[N],f[N],dis[N],q[N*N*2];
    11. inline int read(){
    12. int x=0,f=1;char ch=getchar();
    13. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    14. while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    15. return x*f;
    16. }
    17. inline void add(int x,int y,int z){
    18. e[++tot].v=y;e[tot].cap=z;e[tot].next=head[x];head[x]=tot;
    19. e[++tot].v=x;e[tot].cap=0;e[tot].next=head[y];head[y]=tot;
    20. }
    21. inline bool bfs(){
    22. memset(dis,-1,sizeof dis);
    23. unsigned short h=0,t=1;q[t]=S;dis[S]=0;
    24. while(h!=t){
    25. int x=q[++h];
    26. for(int i=head[x];i;i=e[i].next){
    27. if(e[i].cap&&dis[e[i].v]==-1){
    28. dis[e[i].v]=dis[x]+1;
    29. if(e[i].v==T) return 1;
    30. q[++t]=e[i].v;
    31. }
    32. }
    33. }
    34. return 0;
    35. }
    36. int dfs(int x,int f){
    37. if(x==T) return f;
    38. int used=0,t;
    39. for(int i=head[x];i;i=e[i].next){
    40. if(e[i].cap&&dis[e[i].v]==dis[x]+1){
    41. t=dfs(e[i].v,min(e[i].cap,f));
    42. e[i].cap-=t;e[i^1].cap+=t;
    43. used+=t;f-=t;
    44. if(!f) return used;
    45. }
    46. }
    47. if(!used) dis[x]=-1;
    48. return used;
    49. }
    50. inline int dinic(){
    51. int res=0;
    52. while(bfs()) res+=dfs(S,inf);
    53. return res;
    54. }
    55. inline void DP(){
    56. for(int i=1;i<=n;i++){
    57. f[i]=1;
    58. for(int j=1;j<i;j++){
    59. if(a[i]>=a[j]){
    60. f[i]=max(f[i],f[j]+1);
    61. }
    62. }
    63. }
    64. K=*max_element(f+1,f+n+1);
    65. }
    66. void init(){
    67. n=read();
    68. for(int i=1;i<=n;i++) a[i]=read();
    69. }
    70. void ord_mapping(){
    71. tot=1;memset(head,0,sizeof head);
    72. for(int i=1;i<=n;i++){
    73. for(int j=1;j<i;j++){
    74. if(a[j]<=a[i]&&f[j]+1==f[i]){
    75. add(j+n,i,1);
    76. }
    77. }
    78. }
    79. }
    80. inline void work(){
    81. DP();printf("%d ",K);
    82. S=0,T=n<<1|1;
    83. ord_mapping();
    84. for(int i=1;i<=n;i++){
    85. if(f[i]==1) add(S,i,1);
    86. if(f[i]==K) add(i+n,T,1);
    87. add(i,i+n,1);
    88. }
    89. ans=dinic();
    90. printf("%d ",ans);
    91. ord_mapping();
    92. for(int i=1;i<=n;i++){
    93. int w=1;
    94. if(i==1||i==n) w=inf;
    95. if(f[i]==1) add(S,i,w);
    96. if(f[i]==K) add(i+n,T,w);
    97. add(i,i+n,w);
    98. }
    99. int lastans=ans;
    100. ans=dinic();
    101. if(ans>inf) printf("%d ",lastans);
    102. else printf("%d ",ans);
    103. }
    104. int main(){
    105. setfile(alis);
    106. init();
    107. work();
    108. return 0;
    109. }


  • 相关阅读:
    EOJ 1822 Hanoi Tower IV
    Firefox,chrome,IE上传图片预览
    js保存,获取,删除cookie的操作
    jquery 特效
    SimpleDateFormat转换时间,12,24时间格式[转]
    javascript捕获页面窗口关闭事件
    [转]ajQuery的deferred对象详解
    iframe
    火狐路径问题
    JAVA折腾微信公众平台(Token验证)[转]
  • 原文地址:https://www.cnblogs.com/shenben/p/6538561.html
Copyright © 2011-2022 走看看