PowerOj1741
对于第一个小问我们可以跑一遍dp,求得ans1,和f[]数组,f[i]表示以i结尾的最长上升子序列
对于第二问和第三问,我们考虑把第i个数拆成两个点,ai与bi。
考虑这样建边:
1. 连接ai,bi,限制为1的边
2. 如果f[i]等于ans1,那么连接bi,t,限制为1的边
3. 如果f[i]等于1,连接s,ai,限制为1的边
4. 如果f[i]=f[j]+1且a[i]>a[j],连接一条bj,ai,限制为1的边
对于第二问,我们跑一遍最大流就是答案了。
对于第三问,我们考虑把
<s,a1>,<bn,t>,<a1,b1>,<an,bn>
<script id="MathJax-Element-3" type="math/tex">
,
,
,
</script>这四条边的限制改成无限大再跑一遍最大流就可以了。
#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 5010
#define ll long long
using namespace std;
struct node{
int to,f,m;
node*next,*rev;
}*con[maxn];
int dl[maxn],head,tail,de[maxn];
int n,a[maxn],s,t,v;
bool tag[maxn];
void addedge(int x,int y,int m)
{
node*p=new node;
p->to=y;
p->f=0;
p->m=m;
p->next=con[x];
con[x]=p;
p=new node;
p->to=x;
p->f=0;
p->m=0;
p->next=con[y];
con[y]=p;
con[x]->rev=con[y];
con[y]->rev=con[x];
}
bool bfs()
{
bool tmp=false;
head=1;tail=0;
dl[++tail]=s;
memset(de,0,sizeof(de));
de[s]=1;
while(head<=tail)
{
v=dl[head];
if(v==t) tmp=true;
for(node*p=con[v];p;p=p->next)
if(p->f<p->m&&de[p->to]==0)
dl[++tail]=p->to,de[p->to]=de[v]+1;
head++;
}
return tmp;
}
int dinic(int v,ll e)
{
ll o=0,temp=0;
if(v==t) return e;
if(tag[v]) return 0;
for(node*p=con[v];p;p=p->next)
{
if(de[p->to]==de[v]+1&&p->f<p->m)
{
o=dinic(p->to,min((int)e-(int)temp,(int)p->m-p->f));
temp+=o;
p->f+=o;
p->rev->f-=o;
}
if(temp==e) break;
}
if(temp==0) tag[v]=true;
return temp;
}
int f[maxn];
int ans1=0;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
for(int i=1;i<=n;++i) f[i]=1;
for(int i=1;i<=n;i++)
{
f[i]=1;
for(int j=1;j<i;j++)
if(a[j]<=a[i])f[i]=max(f[i],f[j]+1);
ans1=max(ans1,f[i]);
}
cout<<ans1<<endl;
s=0;t=2*n+1;
for(int i=1;i<=n;++i)
{
if(f[i]==1) addedge(s,i,1);
if(f[i]==ans1) addedge(i+n,t,1);
addedge(i,i+n,1);
}
for(int i=1;i<n;++i)
for(int j=i+1;j<=n;++j)
if(a[j]>=a[i]&&f[j]==f[i]+1) addedge(i+n,j,1);
ll ans2=0;
while(bfs())
{
memset(tag,0,sizeof(tag));
ans2+=dinic(s,0x3f3f3f3f);
}
cout<<ans2<<endl;
for(node*p=con[1];p;p=p->next)
if(p->to==n+1) p->m=0x3f3f3f3f;
for(node*p=con[n];p;p=p->next)
if(p->to==2*n) p->m=0x3f3f3f3f;
for(node*p=con[s];p;p=p->next)
if(p->to==1) p->m=0x3f3f3f3f;
for(node*p=con[2*n];p;p=p->next)
if(p->to==t) p->m=0x3f3f3f3f;
while(bfs())
{
memset(tag,0,sizeof(tag));
ans2+=dinic(s,0x3f3f3f3f);
}
cout<<ans2<<endl;
}