• HDU 3605:Escape(最大流+状态压缩)


    http://acm.hdu.edu.cn/showproblem.php?pid=3605

    题意:有n个人要去到m个星球上,这n个人每个人对m个星球有一个选择,即愿不愿意去,“Y”or"N"。问是否可以全部人都顺利到自己想去的星球。

    思路:很“有趣”的一道题目,n是1e5的大小,m只有10,没有想到状态压缩,看到n这么大肯定超时还是强行写了一波,于是RE(TLE)。想了挺久还是不会。看别人的思路是说二进制状态压缩。看到这就想到m只有10,于是可以分成1<<10 = 1024种情况,代表有这个选择,就相当于把人从1e5的大小强行压到1e3了。然后源点->选择->星球->汇点这样的图就建好了。源点->选择的边权是每种选择的人数,选择->星球的边权是对于每种选择,选择了这个星球的人数,星球->汇点的边权是星球容纳的人数。就酱了。Mark。

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <queue>
      8 #include <vector>
      9 #include <map>
     10 #include <set>
     11 using namespace std;
     12 #define INF 0x3f3f3f3f
     13 #define N 1200
     14 #define NUM 1024
     15 typedef long long LL;
     16 struct Edge {
     17     int v, nxt, cap;
     18     Edge () {}
     19     Edge (int v, int nxt, int cap) : v(v), nxt(nxt), cap(cap) {}
     20 }edge[N*N*2];
     21 int tot, head[N], cur[N], pre[N], dis[N], gap[N], S, T, tol[55];
     22 
     23 void Add(int u, int v, int cap) {
     24     edge[tot] = Edge(v, head[u], cap); head[u] = tot++;
     25     edge[tot] = Edge(u, head[v], 0); head[v] = tot++;
     26 }
     27 
     28 void BFS() {
     29     memset(dis, -1, sizeof(dis));
     30     memset(gap, 0, sizeof(gap));
     31     queue<int> que;
     32     while(!que.empty()) que.pop();
     33     dis[T] = 0; gap[0]++; que.push(T);
     34     while(!que.empty()) {
     35         int u = que.front(); que.pop();
     36         for(int i = head[u]; ~i; i = edge[i].nxt) {
     37             Edge &e = edge[i];
     38             if(dis[e.v] == -1) continue;
     39             dis[e.v] = dis[u] + 1;
     40             que.push(e.v);
     41             gap[dis[e.v]]++;
     42         }
     43     }
     44 }
     45 
     46 int ISAP(int n) {
     47     BFS();
     48     memcpy(cur, head, sizeof(cur));
     49     int ans = 0, i, u = pre[S] = S;
     50     while(dis[S] < n) {
     51         if(u == T) {
     52             int index, flow = INF;
     53             for(i = S; i != T; i = edge[cur[i]].v)
     54                 if(flow > edge[cur[i]].cap)
     55                     flow = edge[cur[i]].cap, index = i;
     56             for(i = S; i != T; i = edge[cur[i]].v)
     57                 edge[cur[i]].cap -= flow, edge[cur[i]^1].cap += flow;
     58             u = index;
     59             ans += flow;
     60         }
     61 //        puts("AAAA");
     62         for(i = cur[u]; ~i; i = edge[i].nxt)
     63             if(dis[edge[i].v] == dis[u] - 1 && edge[i].cap > 0) break;
     64 //        puts("BBBB");
     65         if(~i) {
     66             cur[u] = i; pre[edge[i].v] = u; u = edge[i].v;
     67         } else {
     68             if(--gap[dis[u]] == 0) break;
     69             int md = n;
     70             for(i = head[u]; ~i; i = edge[i].nxt)
     71                 if(dis[edge[i].v] < md && edge[i].cap > 0) cur[u] = i, md = dis[edge[i].v];
     72 //            puts("CCCC");
     73             ++gap[dis[u] = md + 1];
     74 //        puts("ISAP");
     75             u = pre[u];
     76         }
     77     }
     78     return ans;
     79 }
     80 
     81 int main() {
     82     int n, m;
     83     while(~scanf("%d%d", &n, &m)) {
     84         memset(head, -1, sizeof(head));
     85         tot = 0; S = NUM + m + 1, T = NUM + m + 2;
     86         int a; int dp[N][15], s[N];
     87         memset(dp, 0, sizeof(dp));
     88         memset(s, 0, sizeof(s));
     89         for(int i = 1; i <= n; i++) {
     90             int ss = 0;
     91             for(int j = 1; j <= m; j++) {
     92                 scanf("%d", &a);
     93                 if(a) ss |= (a << (j - 1));
     94             }
     95             s[ss]++;
     96             for(int j = 1; j <= m; j++) {
     97                 if(ss & (1 << (j-1))) dp[ss][j]++;
     98             }
     99         }
    100         for(int i = 1; i <= m; i++) scanf("%d", &tol[i]);
    101         for(int i = 0; i <= 1024; i++) {
    102             Add(S, i, s[i]);
    103             for(int j = 1; j <= m; j++) {
    104                 if(dp[i][j]) {
    105                     Add(i, NUM + j, dp[i][j]);
    106                 }
    107             }
    108         }
    109         for(int i = 1; i <= m; i++) Add(NUM + i, T, tol[i]);
    110         int ans = ISAP(T + 1);
    111         if(ans == n) puts("YES");
    112         else puts("NO");
    113 
    114     }
    115     return 0;
    116 }
  • 相关阅读:
    套接字socket
    Windows环境下教你用Eclipse ADT 插件生成.h/.so文件,Java下调用JNI,轻松学习JNI
    How to start/stop DB instance of Oracle under Linux
    Oracle SGA具体解释
    Oracle Study之--Oracle 单实例11.2.0.1.0升级到11.2.0.3.0
    MapReduce(十六): 写数据到HDFS的源代码分析
    Spring表达式语言SpEL简单介绍
    LinkCutTree详解
    洛谷P3379 【模板】最近公共祖先(LCA)(树链剖分)
    树链剖分详解
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6238036.html
Copyright © 2020-2023  润新知