|
- n<=500
- 思路:先用dp求出第一问的答案,和 dp 数组,dp[i]代表以 i为终点最长不下降子序列的长度
- 对于第二问,源点T向 dp[i] 等于第一问答案的点连边,dp[i]=1 的点向汇点S连边,中间的点 u 和点 v ,如果
- dp[u]=dp[v]+1且 a[u]>=a[v] ,那么它们之间连边,这些边容量均为 1 。并且因为每个点只能用一次,所以拆点,
- 中间连容量为 1的边。跑最大流就是第二问的答案,对于第三问,把一号点和最后一个点的拆点的容量与
- 它们连向源点汇点的流量设为 inf 就好了
-
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define maxn 11234 int n,a[maxn],dp[maxn],s1,s2; int cnt,ans,s,t,head[maxn]; int level[maxn]; struct node { int v,to,w; } edge[255678]; void add(int u,int v,int w) { edge[cnt].v=v; edge[cnt].to=head[u]; edge[cnt].w=w; head[u]=cnt++; edge[cnt].v=u; edge[cnt].to=head[v]; edge[cnt].w=0; head[v]=cnt++; } void caldp() { for(int i=1; i<=n; i++) { dp[i]=1; for(int j=i-1; j>=1; j--) if(a[i]>=a[j]) dp[i]=max(dp[i],dp[j]+1); ans=max(dp[i],ans); } } void bulid1() { memset(head,-1,sizeof(head)); s=0,t=n*3; for(int i=1; i<=n; i++) add(i,i+n,1); for(int i=n; i>=1; i--) { if(dp[i]==ans) add(t,i,1); if(dp[i]==1) add(i+n,s,1); for(int j=i-1; j>=1; j--) if(dp[j]+1==dp[i]&&a[i]>=a[j]) add(i+n,j,1); } } void bulid2() { memset(head,-1,sizeof(head)); s=0,t=n*3; for(int i=1; i<=n; i++) { if(i==n||i==1) { add(i,i+n,inf); if(dp[i]==ans)add(t,i,inf); if(dp[i]==1)add(i+n,s,inf); } else { add(i,i+n,1); if(dp[i]==ans)add(t,i,1); if(dp[i]==1)add(i+n,s,1); } } for(int i=n; i>=1; i--) { for(int j=i-1; j>=1; j--) if(dp[j]+1==dp[i]&&a[i]>=a[j]) add(i+n,j,1); } } bool dinic_bfs() { memset(level,0,sizeof(level)); queue<int>que; que.push(t); level[t]=1; while(!que.empty()) { int u=que.front(); que.pop(); for(int i=head[u]; i!=-1; i=edge[i].to) { int v=edge[i].v; if(!level[v]&&edge[i].w>0) { level[v]=level[u]+1; que.push(v); } } } return level[s]!=0; } int dinic_dfs(int u,int cpflow) { if(u==s)return cpflow; int addflow=0; for(int i=head[u]; i!=-1&&addflow<cpflow; i=edge[i].to) { int v=edge[i].v; if(level[u]+1==level[v]&&edge[i].w>0) { int temp=dinic_dfs(v,min(cpflow-addflow,edge[i].w)); edge[i].w-=temp; edge[i^1].w+=temp; addflow+=temp; } } return addflow; } int dinic() { int maxflow=0; while(dinic_bfs()) maxflow+=dinic_dfs(t,inf); return maxflow; } int main() { scanf("%d",&n); for(int i=1; i<=n; i++) scanf("%d",&a[i]); caldp(); bulid1(); s1=dinic(); if(ans==1) printf("1\n%d\n%d\n",s1,n); else { bulid2(); s2=dinic(); printf("%d\n%d\n%d\n",ans,s1,s2); } return 0; }