HDU 3998 Sequence(LIS+最大流-Dinic)
来源:互联网 发布:unity3d射击游戏源码 编辑:程序博客网 时间:2024/05/17 07:55
Description
给出一个长度为n的序列,求其最长上升子序列的长度和满足最长长度的子序列的个数
Input
多组用例,每组用例第一行为一整数n表示序列长度,第二行n个整数表示该序列,以文件尾结束输入
Output
对于每组用例,第一行输出最长上升子序列长度,第二行输出不同的最长上升子序列个数
Sample Input
4
3 6 2 5
Sample Output
2
2
Solution
以dp[i]表示以i结尾的最长上升子序列长度,用朴素的O(n*2)或者优化过的O(n*logn)做法得到dp数组后,考虑将所有最长上升子序列表示在一个网络中:
两排点,因为序列中每个元素在LIS中只能出现一次,从i到i+n建流量为1的边;
dp[i]=1,从源点s到i建流量为1的边;
dp[i]=m,从i+n到汇点e建流量为1的边;
dp[j]=dp[i]+1&&j>i&&a[j]>a[i],从i+n到j建流量为1的边
那么问题就转化为在这个网络中求最大流,跑一边Dinic即可
Code
#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<queue>using namespace std;#define maxn 2222 #define maxm 2222222#define INF 0x3f3f3f3fint head[maxn],cur[maxn],d[maxn],st[maxm],s,e,no;//s为源点,e为汇点,n为点数,no为边数 int a[maxn],dp[maxn],n;//dp[i]表示最长上升子序列,n表示序列长度 int LIS(int a[]){ for(int i=1;i<=n;i++)dp[i]=1; for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(a[j]>a[i]) dp[j]=max(dp[j],dp[i]+1); int ans=0; for(int i=1;i<=n;i++)ans=max(ans,dp[i]); return ans;}struct point{ int u,v,flow,next; point(){}; point(int x,int y,int z,int w):u(x),v(y),next(z),flow(w){};}p[maxm];void add(int x,int y,int z)//从x到y建容量为z的边 { p[no]=point(x,y,head[x],z);//前向弧,标号为偶 head[x]=no++; p[no]=point(y,x,head[y],0);//后向弧,标号为奇 head[y]=no++;}void init()//初始化 { memset(head,-1,sizeof(head)); no=0;}bool bfs(){ int i,x,y; queue<int>q; memset(d,-1,sizeof(d)); d[s]=0; q.push(s); while(!q.empty()) { x=q.front(); q.pop(); for(i=head[x];i!=-1;i=p[i].next) { if(p[i].flow&& d[y=p[i].v]<0) { d[y]=d[x]+1; if(y==e) return true; q.push(y); } } } return false;}int dinic()//最大流 { int i,loc,top,x=s,nowflow,maxflow=0; while(bfs()) { for(i=s;i<=e;i++) cur[i]=head[i]; top=0; while(true) { if(x==e) { nowflow=INF; for(i=0;i<top;i++) { if(nowflow>p[st[i]].flow) { nowflow=p[st[i]].flow; loc=i; } } for(i=0;i<top;i++) { p[st[i]].flow-=nowflow; p[st[i]^1].flow+=nowflow; } maxflow+=nowflow; top=loc; x=p[st[top]].u; } for(i=cur[x];i!=-1;i=p[i].next) if(p[i].flow&&d[p[i].v]==d[x]+1) break; cur[x]=i; if(i!=-1) { st[top++]=i; x=p[i].v; } else { if(!top) break; d[x]=-1; x=p[st[--top]].u; } } } return maxflow;}int main(){ while(~scanf("%d",&n)) { for(int i=1;i<=n;i++)scanf("%d",&a[i]); int m=LIS(a); init(); s=0,e=2*n+1; for(int i=1;i<=n;i++) { add(i,i+n,1); if(dp[i]==1)add(s,i,1); if(dp[i]==m)add(i+n,e,1); for(int j=i+1;j<=n;j++) if(dp[j]==dp[i]+1&&a[j]>a[i]) add(i+n,j,1); } int ans=dinic(); printf("%d\n%d\n",m,ans); } return 0;}
0 0
- HDU 3998 Sequence(LIS+最大流-Dinic)
- hdu 3998 Sequence LIS+最大流
- hdu 3998 Sequence【dp+拆点+最大流--------Dinic】
- HDU3739 Anti LIS 最大流Dinic
- HDU-3998 Sequence LIS统计
- hdu 3998 Sequence(最大流+dp)
- hdu 1532 Drainage Ditches(最大流ek+dinic)
- POJ 1273 && HDU 1532 Drainage Ditches(最大流-Dinic)
- HDU 3572 Task Schedule(最大流-Dinic)
- HDU 5294 Tricks Device(spfa+最大流-Dinic)
- HDU 3572 Task Schedule(最大流Dinic算法)
- hdu 2883 kebab(最大流dinic邻接表)
- hdu 2732 Leapin' Lizards ( Dinic 最大流)【难】
- HDU 5889 Barricade(最短路spfa+最大流dinic)
- Island Transport hdu 4280 (最大流 dinic)
- hdu 1532 网络流-最大流 DINIC
- HDU 1733 escape(最大流 + dinic算法)
- [hdu 1532] Drainage Ditches(最大流dinic)
- 在Java中如何遍历Map对象
- 官网mysql安装
- android涉及的设计模式
- 看图片 读故事:轻松理解数字签名和数字证书
- Spring Security 整合 UM Editor遇到的问题
- HDU 3998 Sequence(LIS+最大流-Dinic)
- openssl证书生成
- Linux手动添加swap分区
- MFC炼狱之旅(二)画图像
- 数据库(八)mysql常用命令(权限相关)
- Ubuntu14.04下Vim的安装并配置成强大的IDE
- 常用正则表达式
- 数据结构之栈
- TODO