zoukankan      html  css  js  c++  java
  • 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
    ", ans == n ? "YES" : "NO");
    139     }
    140     return 0;
    141 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    java-servlet
    oracle 函数
    List 集合的交集
    jsp中表格,表格中的文字根据表格的大小自动换行
    eclipse快捷键调试总结【转】
    Spring(Bean)4 配置数据源、连接池
    Spring(Bean)3
    前端实现表格基于游览器固定显示
    vue下谷歌浏览器的扩展程序(vue-devtools-master)
    前端vue如何下载或者导出word文件和excel文件
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4765847.html
Copyright © 2011-2022 走看看