这道题目的意思是给你一个序列,要你求最长上升子序列,及最多有多少个最长上升子序列(一个数字用过了就不能再用).对于最长上升子序列的dp我就不多说了。下面是对最大流的建图。对于dp[i] = 1的点来说,建立源点到i的边,流量为1,对于dp[i] = 最长长度的时候,建立i到汇点的边,流量为1,对于其他的如果dp[i] + 1 = dp[j]&&num[j] > num[i],那么我们建立i到j的边,流量为1,最后跑一个最大流就好了。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define maxn 2000
#define qq 10000
#define maxm 200005
#define inf (1e8 + 7)
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
int nums[2005], num[2005], heads[2005], sizes, d[2005], dp[2005], que[2005], n, ans1, ans2, source, sink, nn;
bool vis[2005];
struct edge
{
int u, v, w, next;
}eg[8000000];
void inits()
{
mem(num, 0);
mem(vis, 0);
mem(dp, 0);
mem(heads, -1);
mem(d, 0);
sizes = 0;
nn = 0;
ans1 = 1;
return;
}
void add(int u, int v)
{
eg[sizes].v = v;
eg[sizes].w = 1;
eg[sizes].next = heads[u];
heads[u] = sizes++;
eg[sizes].v = u;
eg[sizes].w = 0;
eg[sizes].next = heads[v];
heads[v] = sizes++;
return;
}
void bfs()
{
int head = 0, ta = 0;
mem(vis, 0);
d[sink] = 0;
num[0] = 1;
vis[sink] = 1;
que[head++] = sink;
while(ta != head)
{
int u = que[ta++];
for(int i = heads[u];i != -1;i = eg[i].next)
{
int v = eg[i].v;
if(!vis[v])
{
vis[v] = 1;
d[v] = d[u] + 1;
num[d[v]]++;
que[head++] = v;
}
}
}
return;
}
int dfs(int a, int cos)
{
if(a == sink)
return cos;
int dd, mins = nn + 1, lv = cos;
for(int i = heads[a];i != -1;i = eg[i].next)
{
int v = eg[i].v;
int w = eg[i].w;
if(w)
{
if(d[v] + 1 == d[a])
{
dd = min(lv, w);
dd = dfs(v, dd);
eg[i].w -= dd;
eg[i^1].w += dd;
lv -= dd;
if(d[source] >= nn + 2)
return cos - lv;
if(!lv)
break;
}
mins = min(mins, d[v]);
}
}
if(lv == cos)
{
num[d[a]]--;
if(!num[d[a]])
d[source] = nn + 2;
d[a] = mins + 1;
num[d[a]]++;
}
return cos - lv;
}
int isap()
{
int st = source, ff = 0;
while(d[st] < nn + 2)
ff += dfs(st, inf);
return ff;
}
int main()
{
source = 2003;
sink = 2004;
int a;
while(~scanf("%d", &n))
{
inits();
for(int i = 0;i < n;i++)
scanf("%d", &num[i]);
dp[0] = 1;
for(int i = 1;i < n;i++)
{
bool flag = 0;
for(int j = i - 1;j >= 0;j--)
{
if(num[i] > num[j])
dp[i] = max(dp[i], dp[j] + 1), flag = 1;
}
if(!flag)
dp[i] = 1;
ans1 = max(ans1, dp[i]);
}
add(source, 0);
if(ans1 == 1)
add(0, sink);
nn++;
vis[0] = 1;
for(int i = 1;i < n;i++)
{
if(dp[i] == 1)
{
if(!vis[i])
vis[i] = 1, nn++;
add(source, i);
}
if(dp[i] == ans1)
{
if(!vis[i])
vis[i] = 1, nn++;
add(i, sink);
}
for(int j = i - 1;j >= 0;j--)
{
if(dp[j] + 1 == dp[i]&&num[i] > num[j])
{
add(j, i);
if(!vis[i])
vis[i] = 1, nn++;
if(!vis[j])
vis[j] = 1, nn++;
}
}
}
bfs();
ans2 = isap();
printf("%d\n%d\n", ans1, ans2);
}
return 0;
}