Hdu 3605 Escape (最大流 + 缩点)

题目链接:

  Hdu 3605  Escape

题目描述:

  有n个人要迁移到m个星球,每个星球有最大容量,每个人有喜欢的星球,问是否所有的人都能迁移成功?

解题思路:

  正常情况下建图,不会爆内存,但是TLE还是稳稳的。以前只遇到过网络流拆点建图,这个正好是缩点建图。吼吼吼~~~,建图的方式还是值得学习的。

  因为星球数目最多十个,那么无论有多少个人,其不同选择也就2^10种咯。把不同的选择作为节点,节点就从10^5减少到了2^10,整整缩小了一个数量级呢。建立源点和汇点,源点和选择链接,边权为这种选择的出现次数;每种选择再与可到达的星球相连,边权为INF;星球与汇点相连,边权为星球的最大容量。然后跑最大流,判断是否满流即可。

  1 #include <queue>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 #pragma comment (linker, "/STACK:1024000000,1024000000")
  7 using namespace std;
  8 
  9 const int maxn = 1024;
 10 const int INF = 0x3f3f3f3f;
 11 
 12 struct node
 13 {
 14     int to, next, w;
 15 } edge[maxn*11*2+100];
 16 int head[maxn+100], Layer[maxn+100], Hash[maxn+100], tot;
 17 
 18 void Add (int from, int to, int w)
 19 {
 20     edge[tot].to = to;
 21     edge[tot].w = w;
 22     edge[tot].next = head[from];
 23     head[from] = tot ++;
 24 }
 25 
 26 int Scan ()
 27 {
 28     int res;
 29     char ch;
 30     res = 0;
 31 
 32     while ((ch=getchar())<'0' || ch>'9');
 33 
 34     if (ch>='0' && ch<='9')
 35         res = ch - '0';
 36 
 37     return res;
 38 }
 39 
 40 bool CountLayer (int s, int e)
 41 {
 42     memset (Layer, 0, sizeof(Layer));
 43     queue <int> Q;
 44     Q.push (s);
 45     Layer[s] = 1;
 46     while (!Q.empty())
 47     {
 48         int u = Q.front();
 49         Q.pop();
 50         for (int i=head[u]; i!=-1; i=edge[i].next)
 51         {
 52             int v = edge[i].to;
 53             if (edge[i].w && !Layer[v])
 54             {
 55                 Layer[v] = Layer[u] + 1;
 56                 Q.push (v);
 57                 if (v == e)
 58                     return true;
 59             }
 60         }
 61     }
 62     return false;
 63 }
 64 
 65 int Dfs (int u, int e, int maxflow)
 66 {
 67     if (u == e)
 68         return maxflow;
 69 
 70     int uflow = 0;
 71     for (int i=head[u]; i!=-1; i=edge[i].next)
 72     {
 73         int v = edge[i].to;
 74         if (!edge[i].w || Layer[v] != Layer[u]+1)
 75             continue;
 76 
 77         int flow = min (maxflow-uflow, edge[i].w);
 78         flow = Dfs (v, e, flow);
 79         uflow += flow;
 80         edge[i].w -= flow;
 81         edge[i^1].w += flow;
 82         if (maxflow == uflow)
 83             break;
 84     }
 85     if (uflow == 0)
 86         Layer[u] = 0;
 87     return uflow;
 88 }
 89 
 90 int Dinic (int s, int e)
 91 {
 92     int maxflow = 0;
 93     while (CountLayer (s, e))
 94         maxflow += Dfs (s, e, INF);
 95     return maxflow;
 96 }
 97 
 98 int main ()
 99 {
100     int n, m, s, e, num;
101     while (scanf ("%d %d ", &n, &m) != EOF)
102     {
103         memset (head, -1, sizeof(head));
104         memset (Hash, 0, sizeof(Hash));
105         tot = s = 0;
106         e = (1<<10) + m + 1;
107         for (int i=1; i<=n; i++)
108         {
109             int y, x = 0;
110             for (int j=1; j<=m; j++)
111             {
112                 int y = Scan();
113                 x = x*2 + y;
114             }
115             Hash[x] ++;
116         }
117         
118         for (int i=0; i<maxn; i++)
119         {
120             Add (s, i+1, Hash[i]);
121             Add (i+1, s, 0);
122             for (int j=1; j<=m; j++)
123                 if (i & 1<<(j-1))
124                 {
125                     Add (i+1, maxn+j, INF);
126                     Add (maxn+j, i+1, 0);
127                 }
128         }
129         
130         for (int i=1; i<=m; i++)
131         {
132             scanf ("%d", &num);
133             Add (maxn+i, e, num);
134             Add (e, maxn+i, 0);
135         }
136         
137         int ans = Dinic (s, e);
138         printf ("%s\n", ans == n ? "YES" : "NO");
139     }
140     return 0;
141 }
posted @ 2015-08-28 10:53  罗茜  阅读(219)  评论(0编辑  收藏  举报