• codevs1906 最长递增子序列问题


    题目描述 Description

    给定正整数序列x1,..... , xn  。
    (1)计算其最长递增子序列的长度s。
    (2)计算从给定的序列中最多可取出多少个长度为s的递增子序列。
    (3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长
    度为s的递增子序列。

    输入描述 Input Description

    第1 行有1个正整数n,表示给定序列的长度。接
    下来的1 行有n个正整数x1.....xn 。

    输出描述 Output Description

    第1 行是最长递增子序列的长度s。第2行是可取出的长度为s 的递增子序列个数。第3行是允许在取出的序列中多次使用x1和xn时可取出的长度为s 的递增子序列个数。

    样例输入 Sample Input

    4
    3 6 2 5

    样例输出 Sample Output

    2
    2
    3

    不得不吐槽codevs上面网络流24题好多数据都是很蛋疼的要输出方案又不给spj……鬼知道你数据是用哪种方案啊

    啊这题还算正常

    第一问LIS随便求

    第二问拆点完S向所有x1连流量1费用0的边,所有x2向T连流量1费用0的边,所有x1向x2连流量1费用1的边。因为要表示有没有取这个点

    对于所有a[i]<a[j]且i<j的,i2向j1连流量1费用0的边

    然后跑最大费用。每次增广搞完如果答案是第一问的最长长度,那么ans++。

    第三问就是第二问的建图与1和n有关的边的流量全改inf就对了

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define LL long long
    #define inf 0x3ffffff
    #define S 0
    #define T 1001
    using namespace std;
    inline LL read()
    {
        LL x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,ans,flow,cnt,tot;
    int a[510];
    int mn[510];
    struct edge{int from,to,next,v,c;}e[500010];
    int head[1010],dis[1010],q[1010],from[1010];
    bool mrk[1010];
    inline void ins(int u,int v,int w,int c)
    {
    	e[++cnt].to=v;
    	e[cnt].v=w;
    	e[cnt].c=c;
    	e[cnt].from=u;
    	e[cnt].next=head[u];
    	head[u]=cnt;
    }
    inline void insert(int u,int v,int w,int c)
    {
    	ins(u,v,w,c);
    	ins(v,u,0,-c);
    }
    inline int bsearch(int x)
    {
    	int l=1,r=ans,s=0;
    	while(l<=r)
    	{
    		int mid=(l+r)>>1l;
    		if (mn[mid]<=x){s=mid;l=mid+1;}
    		else r=mid-1;
    	}
    	return s;
    }
    inline bool spfa()
    {
    	for (int i=1;i<=T;i++)dis[i]=inf;
    	memset(mrk,0,sizeof(mrk));
    	int t=0,w=1;
    	dis[S]=0;q[0]=S;mrk[S]=1;
    	while (t!=w)
    	{
    		int now=q[t++];if (t==1005)t=0;
    		for (int i=head[now];i;i=e[i].next)
    		if (e[i].v&&dis[now]+e[i].c<dis[e[i].to])
    		{
    			dis[e[i].to]=dis[now]+e[i].c;
    			from[e[i].to]=i;
    			if (!mrk[e[i].to])
    			{
    				mrk[e[i].to]=1;
    				q[w++]=e[i].to;
    				if (w==1005)w=0;
    			}
    		}
    		mrk[now]=0;
    	}
    	if (dis[T]==inf)return 0;
    	return 1;
    }
    inline void mcf()
    {
    	int x=inf;flow=0;
    	for (int i=from[T];i;i=from[e[i].from])
    		x=min(x,e[i].v);
    	for (int i=from[T];i;i=from[e[i].from])
    		{
    			e[i].v-=x;
    			e[i^1].v+=x;
    			flow+=x*e[i].c;
    		}
    	if (flow==-ans)tot++;
    }
    int main()
    {
    	n=read();
    	for (int i=1;i<=n;i++)a[i]=read();
    	ans=1;mn[1]=a[1];
    	for	(int i=2;i<=n;i++)
    	{
    		int fnd=bsearch(a[i]);
    		if (fnd==ans)mn[++ans]=a[i];
    		else mn[fnd+1]=a[i];
    	}
    	printf("%d
    ",ans);
    	cnt=1;
    	for(int i=1;i<=n;i++)
    	{
    		insert(S,i,1,0);
    		insert(i+n,T,1,0);
    		insert(i,i+n,1,-1);
    	}
    	for (int i=1;i<=n;i++)
    		for (int j=i+1;j<=n;j++)
    			if (a[i]<=a[j])insert(i+n,j,1,0);
    	while (spfa())mcf();
    	printf("%d
    ",tot);
    	memset(head,0,sizeof(head));
    	cnt=1;tot=0;
    	insert(S,1,inf,0);insert(S,n,inf,0);
    	insert(1+n,T,inf,0);insert(2*n,T,inf,0);
    	insert(1,1+n,inf,-1);insert(n,2*n,inf,-1);
    	for(int i=1;i<=n;i++)
    	{
    		insert(S,i,1,0);
    		insert(i+n,T,1,0);
    		insert(i,i+n,1,-1);
    	}
    	for (int i=1;i<n;i++)
    		for (int j=i+1;j<=n;j++)
    			if (a[i]<=a[j])
    				if (i!=1&&j!=n)insert(i+n,j,1,0);
    				else insert(i+n,j,inf,0);
    	while (spfa())mcf();
    	printf("%d
    ",tot);
    }
    

     

    ——by zhber,转载请注明来源
  • 相关阅读:
    调试ASP
    规范的又一个例子
    不同单位转换问题
    客户处出现一个错误
    SQL视图嵌套视图很容易出错
    安装包得到大进步
    两年前的产品现在长得不错
    不用报表的理由
    PowerPoint笔记(五)
    文本编辑器vi
  • 原文地址:https://www.cnblogs.com/zhber/p/4189803.html
Copyright © 2020-2023  润新知