hdu 3998 Sequence(DP+最大流,求最多的不相交路径)
来源:互联网 发布:python java 编辑:程序博客网 时间:2024/06/05 21:50
Sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1149 Accepted Submission(s): 416
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
43 6 2 5
Sample Output
22题意:给出一串序列,求最长上升子序列和最长上升子序列的个数,要求每个数只出现一次。思路:n^2dp求出第一个解,这时就标记了以每一个数为最后一个数的上升子序列的最大长度。因为要求每个数都只出现一次,所以相当于求最多的不相交路线,可用最大流解出。将每个点拆为i和i+1,连i到i+1的边,容量为1,然后源点到每个标记长度为1的边连一条边,容量为1,标记长度为最大长度的点到汇点连一条边,长度也为1。最后对于每个点,排在它后面的且标记长度比它大1的点之间连容量为1的边。AC代码:#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <stack>#include <vector>#include <map>#include <cmath>#include <cstdlib>#define L(rt) (rt<<1)#define R(rt) (rt<<1|1)#define ll __int64#define eps 1e-6using namespace std;const int INF = 1000000000;const int maxn = 1005;struct Edge{ int u, v, cap, flow, next;} et[maxn*maxn];int pre[maxn], cur[maxn], dis[maxn],cnt[maxn], low[maxn], eh[maxn];int a[maxn], dp[maxn];int n, s, t, num;void init(){ memset(eh, -1, sizeof(eh)); num = 0;}void add(int u, int v, int cap, int flow){ Edge e = {u, v, cap, flow, eh[u]}; et[num] = e; eh[u] = num++;}void addedge(int u, int v, int cap){ add(u, v, cap, 0); add(v, u, 0, 0);}int isap(int s, int t, int nv){ int u, v, now, flow = 0; memset(cnt, 0, sizeof(cnt)); memset(low, 0, sizeof(low)); memset(dis, 0, sizeof(dis)); for(u = 0; u <= nv; u++) cur[u] = eh[u]; low[s] =INF, cnt[0] = nv, u = s; while(dis[s] < nv) { for(now = cur[u]; now != -1; now = et[now].next) if(et[now].cap - et[now].flow && dis[u] == dis[v = et[now].v] + 1) break; if(now != -1) { cur[u] = pre[v] = now; low[v] = min(et[now].cap - et[now].flow, low[u]); u = v; if(u == t) { for(; u != s; u = et[pre[u]].u) { et[pre[u]].flow += low[t]; et[pre[u]^1].flow -= low[t]; } flow += low[t]; low[s] = INF; } } else { if(--cnt[dis[u]] == 0) break; dis[u] = nv, cur[u] = eh[u]; for(now = eh[u]; now != -1; now = et[now].next) if(et[now].cap - et[now].flow && dis[u] > dis[et[now].v] + 1) dis[u] = dis[et[now].v] + 1; cnt[dis[u]]++; if(u != s) u = et[pre[u]].u; } } return flow;}int main(){ while(~scanf("%d", &n)) { init(); s = 0; t = 2 * n + 1; for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= n; i++) dp[i] = 1; for(int i = 2; i <= n; i++) for(int j = 1; j < i; j++) if(a[j] < a[i]) dp[i] = max(dp[i], dp[j] + 1); //for(int i = 1; i <= n; i++) cout<<dp[i]<<endl; int ans = 0; for(int i = 1; i <= n; i++) if(dp[i] > ans) ans = dp[i]; for(int i = 1; i <=n; i++) { addedge(i, i + n, 1); if(dp[i] == 1) addedge(s, i, 1); if(dp[i] == ans) addedge(i, t, 1); for(int j = i + 1; j <=n; j++) if(dp[j] == dp[i] + 1) addedge(i + n, j, 1); } printf("%d\n%d\n", ans, isap(s, t, t+1)); } return 0;}
- hdu 3998 Sequence(DP+最大流,求最多的不相交路径)
- hdu 3998 最大流 (最多不相交路径)
- 多校第16场 HDU 3998 Sequence(最多不相交路径)
- 【网络流】 HDU 3998 Sequence 最多不重合路径
- hdu 3998 最长上升子序列个数+网络流 (最多不相交合法路径数)
- 【网络流】HDU 3599 War 最多不相交路径
- [网络流24题] 06 最长递增子序列(最多不相交路径,最大流)
- hdu 3998 Sequence(最大流+dp)
- 求不相交区间的最多个数
- 求最多不相交区间的个数
- HDU 3998 Sequence 最长上升子序列+网络流 求不相交的最长上升子序列个数
- ★ 最长递增子序列问题 (最多不相交路径)(分层思想) 网络流最大流
- !HDU 4293 排队分组说谎问题-dp-(不相交区间的最大个数)
- poj2593 Max Sequence(求两个不相交最大字段和)
- ural 1203. Scientific Conference(dp)给定N个区间,求最大的不相交的区间数
- hdu 5406 CRB and Apple 求两个不相交的不下降子序列之和最大
- POJ 2479 Maximum sum(dp—求最大的两个不相交的字段和)
- HDU 2037 今年暑假不AC (贪心---求最多不相交区间问题)
- 华为面试题:求出用1,2,5这三个数不同个数组合的和为100的组合个数
- 筛选法1
- SAP Solution Manager
- android getLastKnownLocation 返回null
- path2.0 UI path 2.0的华丽转身
- hdu 3998 Sequence(DP+最大流,求最多的不相交路径)
- NEFU84 五指山扩展欧几里德的应用
- 二维码的生成细节和原理
- 怎么将一个十六进制数转变成十进制数
- 迁移Lotus 到Exchange 之同步账户和邮件!
- uva 数学专题入门
- 从头学Android之机器人的意图之Intent的CompentName
- epson打印机设置方法
- 【XCode软件编写一】用代码创建tabcontroller