zoukankan      html  css  js  c++  java
  • 洛谷 P2766 最长不下降子序列问【dp+最大流】

    死于开小数组的WA?!
    第一问n方dp瞎搞一下就成,f[i]记录以i结尾的最长不下降子序列。记答案为mx
    第二问网络流,拆点限制流量,s向所有f[i]为1的点建(s,i,1),所有f[i]为mx(i+n,t,1),然后对于j<i&&a[j]<=a[i]&&f[i]f[j]+1连接(j+n,i,1)表示可以转移,然后跑dinic记录答案ans
    第三问也是网络流但是不用重建图,直接在残量网络上加上(1,1+n,inf)(s,1,inf),如果f[n]
    mx,(n,n+n,inf)(n+n,t,inf),把dinic的结果和上一问的ans加起来即可。

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int N=2000005,inf=1e9;
    int n,h[N],cnt=1,le[N],s,t,f[N],a[N],mx=1;
    struct qwe
    {
    	int ne,to,va;
    }e[N<<2];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void add(int u,int v,int w)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	e[cnt].va=w;
    	h[u]=cnt;
    }
    void ins(int u,int v,int w)
    {
    	add(u,v,w);
    	add(v,u,0);
    }
    bool bfs()
    {
    	queue<int>q;
    	memset(le,0,sizeof(le));
    	le[s]=1;
    	q.push(s);
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		for(int i=h[u];i;i=e[i].ne)
    			if(e[i].va>0&&!le[e[i].to])
    			{
    				le[e[i].to]=le[u]+1;
    				q.push(e[i].to);
    			}
    	}
    	return le[t];
    }
    int dfs(int u,int f)
    {
    	if(u==t||!f)
    		return f;
    	int us=0;
    	for(int i=h[u];i&&us<f;i=e[i].ne)
    		if(e[i].va>0&&le[e[i].to]==le[u]+1)
    		{
    			int t=dfs(e[i].to,min(f-us,e[i].va));
    			e[i].va-=t;
    			e[i^1].va+=t;
    			us+=t;
    		}
    	if(!us)
    		le[u]=0;
    	return us;
    }
    int dinic()
    {
    	int re=0;
    	while(bfs())
    		re+=dfs(s,inf);
    	return re;
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;i++)
    		a[i]=read(),f[i]=1;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<i;j++)
    			if(a[i]>=a[j])
    				f[i]=max(f[i],f[j]+1);
    	for(int i=1;i<=n;i++)
    		mx=max(mx,f[i]);
    	printf("%d
    ",mx);
    	s=0,t=2*n+1;
    	for(int i=1;i<=n;i++)
    	{
    		if(f[i]==1)
    			ins(s,i,1);
    		if(f[i]==mx)
    			ins(i+n,t,1);
    	}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<i;j++)
    			if(a[j]<=a[i]&&f[i]==f[j]+1)
    				ins(j+n,i,1);
    	for(int i=1;i<=n;i++)
    		ins(i,i+n,1);
    	int ans=dinic();
    	printf("%d
    ",ans);
    	ins(1,1+n,inf);
    	ins(s,1,inf);
    	if(f[n]==mx)
    	{
    		ins(n,n+n,inf);
    		ins(n+n,t,inf);
    	}
    	printf("%d
    ",ans+dinic());
    	return 0;
    }
    
  • 相关阅读:
    C++中整型变量的存储大小和范围
    A1038 Recover the Smallest Number (30 分)
    A1067 Sort with Swap(0, i) (25 分)
    A1037 Magic Coupon (25 分)
    A1033 To Fill or Not to Fill (25 分)
    A1070 Mooncake (25 分)
    js 获取控件
    C#代码对SQL数据库添加表或者视图
    JS 动态操作表格
    jQuery取得下拉框选择的文本与值
  • 原文地址:https://www.cnblogs.com/lokiii/p/8425302.html
Copyright © 2011-2022 走看看