HDU 3998 Sequence 最大流 isap 加 dp
2015-09-01 22:42
363 查看
这道题目的意思是给你一个序列,要你求最长上升子序列,及最多有多少个最长上升子序列(一个数字用过了就不能再用).对于最长上升子序列的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; }
相关文章推荐
- leetcode 232 Implement Queue using Stacks
- 部署Mirantis OpenStack与Fuel的系统配置要求说明
- iOS 在UILabel显示不同的字体和颜色
- 图片拉伸通常我们开发中将其写到UIImage的分类中使用,下面可以直接复制使用
- UIday0703:用 UIScrollView 和 UIPageControl 实现轮播图
- UI多线程编程小练习--卖票系统
- UIday0702:用 UIScrollView 和 UIPageControl 实现引导图
- hdu 2818 Building Block (带权并查集,很优美的题目)
- 将UIView加载成WevView(不懂的可以留言)
- UI中常用的4种传值
- Win10开发:视觉状态VisualState与自适应UI
- UITabBar 自定义
- AbstractQueuedSynchronizer实现原理
- UVALive 4287 Proving Equivalence (强连通分量)
- Android UI设计(引导界面):ViewPager之基本用法
- java基础-GUI
- [DP!]UESTC 890
- LeetCode之Repeated DNA Sequences
- UI_UIGestureRecognizer(触摸手势)
- UINavigationController视图控制器