洛谷P2766最长不下降子序列

第一问dp一下就好

第二问

把一个数分成两个点,i,i+n,

i到i+n建一条边容量为1的边,表示这个数可以选一次

0为源点,2n+1为汇点,0,i建一条边容量为1的边表示有以i开头长度为max的最长不下降序列,

i+n,hui建一条边容量为1的边表示有以i结尾长度为max的最长不下降序列,

跑最大流

第三问  残余网络(表示还剩那些数未选)

建立四条边

 add(1,n+1,1e9),add(huan,1,1e9);
add(n,n+n,1e9),add(n+n,hui,1e9);(因为只有n前面有max-1个数小于它时,它才能做最后一个数)

再跑一遍最大流+上上一题答案

#include
#include
#include
using namespace std;
int num[1505],n,f[505],huan,hui;
int tov[20005],tow[20005],h[1505],nex[20005],tp=1;
int dis[1505],q[2000005],vis[1505];
void add(int x,int y,int w)
{
    tp++;
    tov[tp]=y;
    tow[tp]=w;
    nex[tp]=h[x];
    h[x]=tp;
    tp++;
    tov[tp]=x;
    tow[tp]=0;
    nex[tp]=h[y];
    h[y]=tp;
}
int dfs()
{
    memset(dis,0,sizeof(dis));
    memset(vis,0,sizeof(vis));
    memset(q,0,sizeof(q));
    int tail=1,head=0;
    dis[huan]=0;
    vis[huan]=1;
    q[tail]=huan;
    while(head0)
            {
                vis[v]=1;
                dis[v]=dis[x]+1;
                tail++;
                q[tail]=v;
            }
        }
    }
 return vis[hui];	
}
int bfs(int x,int delta)
{
    if(x==hui)return delta;
    int ret=0;
    for(int i=h[x];i;i=nex[i])
    {
        int v=tov[i];
        if(tow[i]>0&&dis[v]==dis[x]+1)
        {
        int dd=bfs(v,min(delta,tow[i]));
        delta-=dd;
        tow[i]-=dd;
        tow[i^1]+=dd;
        ret+=dd;
        }
    }
    return ret;
}
int main()
{
  cin>>n;
  for(int i=1;i<=n;i++)
  scanf("%d",&num[i]);
  for(int i=1;i<=n;i++)
  {
  	f[i]=1;
  	for(int j=1;j=num[j])f[i]=max(f[i],f[j]+1);
  }
  int ans=0;huan=0,hui=2*n+1;
  for(int i=1;i<=n;i++)
  {
  ans=max(ans,f[i]);
  }
  printf("%d\n",ans);
  for(int i=1;i<=n;i++)
  {
      add(i,i+n,1);
  	if(f[i]==ans){add(i+n,hui,1);}
  	if(f[i]==1){add(huan,i,1);}
  }
  for(int i=1;i<=n;i++)
  for(int j=1;j=num[j]&&f[i]==f[j]+1)
  	{
  		add(j+n,i,1);
     }
  }
   int ans2=0;
  while(dfs())
  {
  	ans2+=bfs(huan,1e9);
  }
  printf("%d\n",ans2);
   add(1,n+1,1e9),add(huan,1,1e9);add(n,n+n,1e9);
 if(f[n]==ans) add(n+n,hui,1e9);
   int ans1=0;
  while(dfs())
  {
  	ans1+=bfs(huan,1e9);
  }
  ans1+=ans2;
   printf("%d",ans1); 
   return 0;
}

 

 

 

 

你可能感兴趣的:(网络流,dp)