Sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1164 Accepted Submission(s): 421
Problem Description
There is a sequence X (i.e. x[1], x[2], ..., x[n]). We define increasing subsequence of X
as x[i1], x[i2],...,x[ik], which satisfies follow conditions:
1) x[i1] < x[i2],...,<x[ik];
2) 1<=i1 < i2,...,<ik<=n
As an excellent program designer, you must know how to find the maximum length of the
increasing sequense, which is defined as s. Now, the next question is how many increasing
subsequence with s-length can you find out from the sequence X.
For example, in one case, if s = 3, and you can find out 2 such subsequence A and B from X.
1) A = a1, a2, a3. B = b1, b2, b3.
2) Each ai or bj(i,j = 1,2,3) can only be chose once at most.
Now, the question is:
1) Find the maximum length of increasing subsequence of X(i.e. s).
2) Find the number of increasing subsequence with s-length under conditions described (i.e. num).
as x[i1], x[i2],...,x[ik], which satisfies follow conditions:
1) x[i1] < x[i2],...,<x[ik];
2) 1<=i1 < i2,...,<ik<=n
As an excellent program designer, you must know how to find the maximum length of the
increasing sequense, which is defined as s. Now, the next question is how many increasing
subsequence with s-length can you find out from the sequence X.
For example, in one case, if s = 3, and you can find out 2 such subsequence A and B from X.
1) A = a1, a2, a3. B = b1, b2, b3.
2) Each ai or bj(i,j = 1,2,3) can only be chose once at most.
Now, the question is:
1) Find the maximum length of increasing subsequence of X(i.e. s).
2) Find the number of increasing subsequence with s-length under conditions described (i.e. num).
Input
The input file have many cases. Each case will give a integer number n.The next line will
have n numbers.
have n numbers.
Output
The output have two line. The first line is s and second line is num.
Sample Input
4 3 6 2 5
Sample Output
2 2
题意:求最长上升子序列的长度以及个数。
解题思路:先求最长上升子序列,
然后添加一个源点,一个汇点,对每个点拆点,假如dp[i]=1那么从源点向i连流量为1,的边,如果dp[i]=k从i+n向汇点连流量为1的边,如果i<j,且dp[i]+1=dp[j],则连边,
然后最大流。
代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=10000;
int head[maxn],tol,dep[maxn],n;
struct node
{
int next,to,from,cap;
}edge[300000];
void add(int u,int v,int cap)
{
edge[tol].from=u;
edge[tol].to=v;
edge[tol].cap=cap;
edge[tol].next=head[u];
head[u]=tol++;
edge[tol].from=v;
edge[tol].to=u;
edge[tol].cap=0;
edge[tol].next=head[v];
head[v]=tol++;
}
int bfs(int s,int t)
{
int que[maxn],front=0,rear=0;
memset(dep,-1,sizeof(dep));
dep[s]=0;que[rear++]=s;
while(front!=rear)
{
int u=que[front++];front%=maxn;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap>0&&dep[v]==-1)
{
dep[v]=dep[u]+1;
que[rear++]=v;
rear%=maxn;
if(v==t)return 1;
}
}
}
return 0;
}
int dinic(int s,int t)
{
int i,res=0,top;
int Stack[maxn],cur[maxn];
while(bfs(s,t))
{
memcpy(cur,head,sizeof(head));
int u=s;top=0;
while(1)
{
if(u==t)
{
int min=inf,loc;
for(int i=0;i<top;i++)
if(min>edge[Stack[i]].cap)
{
min=edge[Stack[i]].cap;
loc=i;
}
for(int i=0;i<top;i++)
{
edge[Stack[i]].cap-=min;
edge[Stack[i]^1].cap+=min;
}
res+=min;
top=loc;
u=edge[Stack[top]].from;
}
for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)
if(edge[i].cap&&dep[u]+1==dep[edge[i].to])break;
if(cur[u]!=-1)
{
Stack[top++]=cur[u];
u=edge[cur[u]].to;
}
else
{
if(top==0)break;
dep[u]=-1;
u=edge[Stack[--top]].from;
}
}
}
return res;
}
int a[30000],dp[30000];
int main()
{
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
int i,j,k,m,n;
while(~scanf("%d",&n))
{
memset(head,-1,sizeof(head));tol=0;
for(i=1;i<=n;i++)scanf("%d",&a[i]);
int ans=0;
for(i=1;i<=n;i++)
{
dp[i]=1;
for(j=1;j<i;j++)
if(a[j]<a[i]&&dp[j]>=dp[i])
dp[i]=dp[j]+1;
ans=max(ans,dp[i]);
}
// for(i=1;i<=n;i++)cout<<dp[i]<<" ";cout<<endl;
// cout<<ans<<endl;
for(i=1;i<=n;i++)
{
add(i,i+n,1);
if(dp[i]==1)add(0,i,1);
if(dp[i]==ans)add(i+n,2*n+1,1);
for(j=i+1;j<=n;j++)
if(dp[j]==dp[i]+1)
add(i+n,j,1);
}
// cout<<tol<<endl;
int flow=dinic(0,2*n+1);
//if(flow==0)flow++;
printf("%d\n%d\n",ans,flow);
}
return 0;
}