【网络流24题】 No.6 最长不减子序列问题 (最大流)[模型:最多不相交路径]...

【题意】  

给定正整数序列x1 ,x2 , x3...

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

输入文件示例
input.txt
4
3 6 2 5


输出文件示例
output.txt
2
2
3

 

【题意】

  数据比较小。

  首先算出LIS,(n^2都可以了)

  然后连边,这题点也有流量哦,所以要拆点。(一个点拆两个,一个负责进,一个负责出)

  st->u1 流量为1  (f[u]==mx) mx为第一问答案,f为求LIS的数组

     u2->ed 流量为1 (f[u]==1)

  每个点 u1->u2 流量为1

  对于 f[i]==f[j]+1 且a[i]>a[j] i>j : i2->j1 流量为1

  然后跑最大流就是第二问。

 

  对于第三问,实际上表示1和n是不用拆点的。

  在残量网络上加边 st->n 流量为INF (当f[n]==mx)

  1->ed 流量为INF

  1->1 INF   n1->n2 INF

  然后继续跑最大流,累加上第二问的答案就是第三问答案。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<cmath>
  8 using namespace std;
  9 #define Maxn 1010
 10 #define INF 0xfffffff
 11 
 12 struct node
 13 {
 14     int x,y,f,o,next;
 15 }t[Maxn*1010];int len;
 16 int first[Maxn];
 17 
 18 int mymin(int x,int y) {return x<y?x:y;}
 19 int mymax(int x,int y) {return x>y?x:y;}
 20 
 21 void ins(int x,int y,int f)
 22 {
 23     t[++len].x=x;t[len].y=y;t[len].f=f;
 24     t[len].next=first[x];first[x]=len;t[len].o=len+1;
 25     t[++len].x=y;t[len].y=x;t[len].f=0;
 26     t[len].next=first[y];first[y]=len;t[len].o=len-1;
 27 }
 28 
 29 int st,ed;
 30 queue<int > q;
 31 int dis[Maxn];
 32 bool bfs()
 33 {
 34     while(!q.empty()) q.pop();
 35     memset(dis,-1,sizeof(dis));
 36     q.push(st);dis[st]=0;
 37     while(!q.empty())
 38     {
 39         int x=q.front();
 40         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
 41         {
 42             int y=t[i].y;
 43             if(dis[y]==-1)
 44             {
 45                 dis[y]=dis[x]+1;
 46                 q.push(y);
 47             }
 48         }
 49         q.pop();
 50     }
 51     if(dis[ed]==-1) return 0;
 52     return 1;
 53 }
 54 
 55 int ffind(int x,int flow)
 56 {
 57     if(x==ed) return flow;
 58     int now=0;
 59     for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
 60     {
 61         int y=t[i].y;
 62         if(dis[y]==dis[x]+1)
 63         {
 64             int a=ffind(y,mymin(flow-now,t[i].f));
 65             t[i].f-=a;
 66             t[t[i].o].f+=a;
 67             now+=a;
 68         }
 69         if(now==flow) break;
 70     }
 71     if(now==0) dis[x]=-1;
 72     return now;
 73 }
 74 
 75 void output()
 76 {
 77     for(int i=1;i<=len;i+=2)
 78      printf("%d->%d %d\n",t[i].x,t[i].y,t[i].f);
 79 }
 80 
 81 int max_flow()
 82 {
 83     int ans=0;
 84     while(bfs())
 85     {
 86         ans+=ffind(st,INF);
 87         // printf("--%d\n",ans);
 88         // output();
 89     }
 90     return ans;
 91 }
 92 
 93 int n,ans=0;
 94 int a[Maxn],f[Maxn];
 95 
 96 void init()
 97 {
 98     scanf("%d",&n);
 99     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
100     for(int i=1;i<=n;i++)
101     {
102         f[i]=1;
103         for(int j=1;j<i;j++) if(a[i]>=a[j])
104           f[i]=mymax(f[i],f[j]+1);
105         ans=mymax(ans,f[i]);
106     }
107     printf("%d\n",ans);
108 }
109 
110 int main()
111 {
112     init();
113     len=0;
114     memset(first,0,sizeof(first));
115     st=n*2+1;ed=st+1;
116     for(int i=1;i<=n;i++) ins(i,i+n,1);
117     for(int i=1;i<=n;i++) if(f[i]==1) ins(i+n,ed,1);
118     for(int i=1;i<=n;i++) if(f[i]==ans) ins(st,i,1);
119     for(int i=1;i<=n;i++)
120      for(int j=i+1;j<=n;j++) if(f[j]==f[i]+1&&a[j]>=a[i]) ins(j+n,i,1);
121     int x=max_flow();
122     printf("%d\n",x);
123     
124     if(f[n]==ans) ins(st,n,INF);
125     ins(1+n,ed,INF);ins(1,1+n,INF);ins(n,n+n,INF);
126     x+=max_flow();
127     printf("%d\n",x);
128     return 0;
129 }
View Code

 

 

2016-11-04 14:05:24

  

 

转载于:https://www.cnblogs.com/Konjakmoyu/p/6030037.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值