题意:
思路:
【问题分析】
第一问时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可以重复使用,只需取消这两个点相关边的流量限制,求网络最大流即可。
实质上也只有两层,不如叫裂点
单位网络的最大流就是增广路的条数 这个性质需要记住
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef long double ld; 7 typedef pair<int,int> PII; 8 typedef pair<ll,ll> Pll; 9 typedef vector<int> VI; 10 typedef vector<PII> VII; 11 typedef pair<ll,ll>P; 12 #define N 100010 13 #define M 1000000 14 #define INF 1e9 15 #define fi first 16 #define se second 17 #define MP make_pair 18 #define pb push_back 19 #define pi acos(-1) 20 #define mem(a,b) memset(a,b,sizeof(a)) 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++) 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--) 23 #define lowbit(x) x&(-x) 24 #define Rand (rand()*(1<<16)+rand()) 25 #define id(x) ((x)<=B?(x):m-n/(x)+1) 26 #define ls p<<1 27 #define rs p<<1|1 28 29 const ll MOD=1e9+7,inv2=(MOD+1)/2; 30 double eps=1e-6; 31 int dx[4]={-1,1,0,0}; 32 int dy[4]={0,0,-1,1}; 33 34 int head[N],vet[N],len[N],nxt[N],dp[N],a[N],dis[N],num[N][2],s,S,T,K,n,tot; 35 36 int read() 37 { 38 int v=0,f=1; 39 char c=getchar(); 40 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 41 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 42 return v*f; 43 } 44 45 void add(int a,int b,int c) 46 { 47 nxt[++tot]=head[a]; 48 vet[tot]=b; 49 len[tot]=c; 50 head[a]=tot; 51 52 nxt[++tot]=head[b]; 53 vet[tot]=a; 54 len[tot]=0; 55 head[b]=tot; 56 } 57 58 bool bfs() 59 { 60 queue<int>q; 61 rep(i,1,s) dis[i]=-1; 62 q.push(S),dis[S]=0; 63 while(!q.empty()) 64 { 65 int u=q.front(); 66 q.pop(); 67 int e=head[u]; 68 while(e) 69 { 70 int v=vet[e]; 71 if(len[e]&&dis[v]==-1) 72 { 73 dis[v]=dis[u]+1; 74 q.push(v); 75 } 76 e=nxt[e]; 77 } 78 } 79 return dis[T]!=-1; 80 } 81 82 int dfs(int u,int aug) 83 { 84 if(u==T) return aug; 85 int e=head[u],val=0,flow=0; 86 while(e) 87 { 88 int v=vet[e]; 89 if(len[e]&&dis[v]==dis[u]+1) 90 { 91 int t=dfs(v,min(len[e],aug)); 92 if(!t) 93 { 94 e=nxt[e]; 95 continue; 96 } 97 flow+=t; 98 aug-=t; 99 len[e]-=t; 100 len[e^1]+=t; 101 if(!aug) break; 102 } 103 e=nxt[e]; 104 } 105 if(!flow) dis[u]=-1; 106 return flow; 107 } 108 109 int maxflow() 110 { 111 int res=0; 112 while(bfs()) res+=dfs(S,INF); 113 return res; 114 } 115 116 void solve1() 117 { 118 s=0; 119 rep(i,1,n) 120 rep(j,0,1) num[i][j]=++s; 121 S=++s; 122 T=++s; 123 rep(i,1,s) head[i]=0; 124 tot=1; 125 rep(i,1,n) add(num[i][0],num[i][1],1); 126 rep(i,1,n) 127 if(dp[i]==1) add(S,num[i][0],1); 128 rep(i,1,n) 129 if(dp[i]==K) add(num[i][1],T,1); 130 rep(i,1,n) 131 rep(j,i+1,n) 132 if(a[j]>a[i]&&dp[j]==dp[i]+1) add(num[i][1],num[j][0],1); 133 int ans=maxflow(); 134 printf("%d ",ans); 135 } 136 137 void solve2() 138 { 139 rep(i,1,s) head[i]=0; 140 tot=1; 141 add(num[1][0],num[1][1],INF); 142 add(num[n][0],num[n][1],INF); 143 rep(i,2,n-1) add(num[i][0],num[i][1],1); 144 rep(i,1,n) 145 if(dp[i]==1) 146 { 147 if(i==1||i==n) add(S,num[i][0],INF); 148 else add(S,num[i][0],1); 149 } 150 151 rep(i,1,n) 152 if(dp[i]==K) 153 { 154 if(i==1||i==n) add(num[i][1],T,INF); 155 else add(num[i][1],T,1); 156 } 157 158 rep(i,1,n) 159 rep(j,i+1,n) 160 if(a[j]>a[i]&&dp[j]==dp[i]+1) add(num[i][1],num[j][0],1); 161 int ans=maxflow(); 162 if(ans>INF) ans=n; 163 printf("%d ",ans); 164 } 165 166 int main() 167 { 168 //freopen("1.in","r",stdin); 169 n=read(); 170 rep(i,1,n) a[i]=read(); 171 rep(i,1,n) 172 { 173 dp[i]=1; 174 rep(j,1,i-1) 175 if(a[j]<a[i]) dp[i]=max(dp[i],dp[j]+1); 176 } 177 K=1; 178 rep(i,1,n) K=max(K,dp[i]); 179 printf("%d ",K); 180 solve1(); 181 solve2(); 182 return 0; 183 }