zoukankan      html  css  js  c++  java
  • [HDOJ3998] Sequence(DP,最大流)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3998

    给数字,问LIS以及每一个数字只取一次,最多能取多少个LIS。

    LIS直接O(n^2) dp即可。

    关键是怎么在统计最多能取多少个不相交的LIS:

    每个数作为一个点,假如dp(i)=1,则说明这个点作为起点是不亏的,假如dp(i)=LIS,那么这个点肯定有机会是最后一个点。这样源点和汇点的边就建好:

    源点 到 dp(i)=1 容量为1

    dp(i)=LIS 到 汇点 容量为1

    还要描述点与点之间的关系,所以不要忘记拆点。左半部分记为A集合,右半部分记为B集合。

    A到B同位置的点要连一条边,容量为1。保证可以从A侧到B侧。

    接下来可以枚举任意两个点i j,满足恰好的递推关系就行:i > j && x(i)>x(j) && dp(i)=dp(j)+1,则j到i连一条边,容量为1(注意是从B集合到A集合哦,不然的话只有A到B是不能满足匹配的)。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 typedef struct Edge {
      5     int u, v, w, next;
      6 }Edge;
      7 
      8 const int inf = 0x7f7f7f7f;
      9 const int maxn = 6660;
     10 
     11 int cnt, dhead[maxn];
     12 int cur[maxn], dd[maxn];
     13 Edge dedge[maxn<<8];
     14 int S, T, N;
     15 
     16 void init() {
     17     memset(dhead, -1, sizeof(dhead));
     18     for(int i = 0; i < maxn; i++) dedge[i].next = -1;
     19     S = 0; cnt = 0;
     20 }
     21 
     22 void adde(int u, int v, int w, int c1=0) {
     23     dedge[cnt].u = u; dedge[cnt].v = v; dedge[cnt].w = w; 
     24     dedge[cnt].next = dhead[u]; dhead[u] = cnt++;
     25     dedge[cnt].u = v; dedge[cnt].v = u; dedge[cnt].w = c1; 
     26     dedge[cnt].next = dhead[v]; dhead[v] = cnt++;
     27 }
     28 
     29 bool bfs(int s, int t, int n) {
     30     queue<int> q;
     31     for(int i = 0; i < n; i++) dd[i] = inf;
     32     dd[s] = 0;
     33     q.push(s);
     34     while(!q.empty()) {
     35         int u = q.front(); q.pop();
     36         for(int i = dhead[u]; ~i; i = dedge[i].next) {
     37             if(dd[dedge[i].v] > dd[u] + 1 && dedge[i].w > 0) {
     38                 dd[dedge[i].v] = dd[u] + 1;
     39                 if(dedge[i].v == t) return 1;
     40                 q.push(dedge[i].v);
     41             }
     42         }
     43     }
     44     return 0;
     45 }
     46 
     47 int dinic(int s, int t, int n) {
     48     int st[maxn], top;
     49     int u;
     50     int flow = 0;
     51     while(bfs(s, t, n)) {
     52         for(int i = 0; i < n; i++) cur[i] = dhead[i];
     53         u = s; top = 0;
     54         while(cur[s] != -1) {
     55             if(u == t) {
     56                 int tp = inf;
     57                 for(int i = top - 1; i >= 0; i--) {
     58                     tp = min(tp, dedge[st[i]].w);
     59                 }
     60                 flow += tp;
     61                 for(int i = top - 1; i >= 0; i--) {
     62                     dedge[st[i]].w -= tp;
     63                     dedge[st[i] ^ 1].w += tp;
     64                     if(dedge[st[i]].w == 0) top = i;
     65                 }
     66                 u = dedge[st[top]].u;
     67             }
     68             else if(cur[u] != -1 && dedge[cur[u]].w > 0 && dd[u] + 1 == dd[dedge[cur[u]].v]) {
     69                 st[top++] = cur[u];
     70                 u = dedge[cur[u]].v;
     71             }
     72             else {
     73                 while(u != s && cur[u] == -1) {
     74                     u = dedge[st[--top]].u;
     75                 }
     76                 cur[u] = dedge[cur[u]].next;
     77             }
     78         }
     79     }
     80     return flow;
     81 }
     82 
     83 int n;
     84 int x[maxn];
     85 int dp[maxn];
     86 int ret;
     87 
     88 void work1() {
     89     ret = 0;
     90     memset(dp, 0, sizeof(dp));
     91     for(int i = 1; i <= n; i++) {
     92         dp[i] = 1;
     93         for(int j = 1; j <= i; j++) {
     94             if(x[i] > x[j]) dp[i] = max(dp[i], dp[j]+1);
     95         }
     96         ret = max(ret, dp[i]);
     97     }
     98     printf("%d
    ", ret);
     99 }
    100 
    101 void work2() {
    102     if(ret == 1) {
    103         printf("%d
    ", n);
    104         return;
    105     }
    106     init();
    107     S = 0, T = 2 * n + 1, N = T + 1;
    108     for(int i = 1; i <= n; i++) {
    109         adde(i, i+n, 1);
    110         if(dp[i] == 1) adde(S, i, 1);
    111         if(dp[i] == ret) adde(i+n, T, 1);
    112     }
    113     for(int i = 2; i <= n; i++) {
    114         for(int j = 1; j < i; j++) {
    115             if(x[i] > x[j] && dp[i] == dp[j] + 1) {
    116                 adde(j+n, i, 1);
    117             }
    118         }
    119     }
    120     cout << dinic(S, T, N) << endl;
    121 }
    122 
    123 int main() {
    124     // freopen("in", "r", stdin);
    125     while(~scanf("%d",&n)) {
    126         init();
    127         for(int i = 1; i <= n; i++) scanf("%d", &x[i]);
    128         work1(); work2();
    129     }
    130     return 0;
    131 }
  • 相关阅读:
    Eclipse 远程调试
    大数据处理方法bloom filter
    sicily 1259 Sum of Consecutive Primes
    sicily 1240. Faulty Odometer
    sicily 1152 简单马周游 深度优先搜索及回溯算法
    sicily 1050 深度优先搜索解题
    sicily 1024 邻接矩阵与深度优先搜索解题
    sicily 1156 二叉树的遍历 前序遍历,递归,集合操作
    sicily 1443 队列基本操作
    sicily 1006 team rankings 枚举解题
  • 原文地址:https://www.cnblogs.com/kirai/p/6832425.html
Copyright © 2011-2022 走看看