Loading

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 }

 

posted @ 2016-12-30 19:07  Shadowdsp  阅读(267)  评论(0编辑  收藏  举报