【网络流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 }
2016-11-04 14:05:24