zoukankan      html  css  js  c++  java
  • BZOJ3577:玩手机(最大流,二维ST表)

    Description

    现在有一堆手机放在坐标网格里面(坐标从1开始),坐标(i,j)的格子有s_(i,j)个手机。
    玩手机当然需要有信号,不过这里的手机与基站与我们不太一样。基站分为两种:发送站和接收站(以下简称为A站和B站)。每个手机必须同时与一个A站和一个B站通信才能工作。
    每个基站有一个正方形的覆盖范围(平行于网格)。覆盖范围可以用左下角和右上角的坐标表示(范围包括边角)。显然,手机只有在某个基站的范围内才能与这个基站通信。除此之外,每个基站还有最大接入的手机数量限制。
    求最大同时工作的手机数量。

    Input

    第一行四个整数R,C,a,b,表示坐标网格的规模是R×C,共有a个A站和b个B站。
    接下来是一个R×C的矩阵,第i行第j列的数为s_(i,j)。
    接下来a行,每行5个数w,x1,y1,x2,y2,表示第i个A站最大接入w个手机,覆盖范围为(x1,y1)~(x2,y2)。
    接下来b行,每行5个数w,x1,y1,x2,y2,含义同上。

    Output

    一个整数,即最大同时工作的手机数量。

    Sample Input

    3 3 1 2
    1 1 1
    1 1 1
    1 1 1
    100 1 1 3 3
    4 1 1 2 2
    4 2 2 3 3

    Sample Output

    7

    数据规模与约定
    1≤R,C≤60,0≤a,b≤10,000,0≤s,w≤10,000,1≤x1≤x2≤R,1≤y1≤y2≤C。

    Solution

    朴素的网络流应该很简单,直接$r imes c$的每个格子拆点,左边连$a$基站右边连$b$基站,然后$a$基站连源点,$b$基站连汇点就好了。

    但是这样的话会边数爆炸,所以可以用二维$ST$表优化连边。具体的可以看$Claris$神仙的博客QwQ

    Code

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<queue>
      5 #define N (300009)
      6 #define INF (0x7f7f7f7f)
      7 using namespace std;
      8 
      9 struct Edge{int to,next,flow;}edge[N<<2];
     10 int r,c,a,b,w,x,y,u,v,id_num,val,s,t=300000;
     11 int Depth[N],f[69][69][10],g[69][69][10],LOG2[69];
     12 int head[N],num_edge;
     13 queue<int>q;
     14 
     15 void add(int u,int v,int l)
     16 {
     17     edge[++num_edge]=(Edge){v,head[u],l}; head[u]=num_edge;
     18     edge[++num_edge]=(Edge){u,head[v],0}; head[v]=num_edge;
     19 }
     20 
     21 int DFS(int x,int low,int t)
     22 {
     23     if (x==t || !low) return low;
     24     int f=0;
     25     for (int i=head[x]; i; i=edge[i].next)
     26         if (Depth[edge[i].to]==Depth[x]+1)
     27         {
     28             int Min=DFS(edge[i].to,min(low,edge[i].flow),t);
     29             edge[i].flow-=Min;
     30             edge[((i-1)^1)+1].flow+=Min;
     31             f+=Min; low-=Min;
     32             if (!low) break;
     33         }
     34     if (!f) Depth[x]=-1;
     35     return f;
     36 }
     37 
     38 bool BFS(int s,int t)
     39 {
     40     memset(Depth,0,sizeof(Depth));
     41     Depth[s]=1;
     42     q.push(s);
     43     while (!q.empty())
     44     {
     45         int x=q.front(); q.pop();
     46         for (int i=head[x]; i; i=edge[i].next)
     47             if (!Depth[edge[i].to] && edge[i].flow)
     48             {
     49                 Depth[edge[i].to]=Depth[x]+1;
     50                 q.push(edge[i].to);
     51             }
     52     }
     53     return Depth[t];
     54 }
     55 
     56 int Dinic(int s,int t)
     57 {
     58     int ans=0;
     59     while (BFS(s,t))
     60         ans+=DFS(s,INF,t);
     61     return ans;
     62 }
     63 
     64 int main()
     65 {
     66     for (int i=2; i<=60; ++i) LOG2[i]=LOG2[i>>1]+1;
     67     scanf("%d%d%d%d",&r,&c,&a,&b);
     68     for (int i=1; i<=r; ++i)
     69         for (int j=1; j<=c; ++j)
     70         {
     71             scanf("%d",&val);
     72             f[i][j][0]=++id_num; g[i][j][0]=++id_num;
     73             add(f[i][j][0],g[i][j][0],val);
     74         }
     75     for(int k=1; k<6; ++k)
     76         for(int i=1; i<=r; ++i)
     77             for(int j=1; j<=c; ++j)
     78                 if(i+(1<<k)-1<=r && j+(1<<k)-1<=c)
     79                 {
     80                     f[i][j][k]=++id_num; g[i][j][k]=++id_num;
     81                     add(f[i][j][k],f[i][j][k-1],INF); add(g[i][j][k-1],g[i][j][k],INF);
     82                     add(f[i][j][k],f[i+(1<<k-1)][j][k-1],INF); add(g[i+(1<<k-1)][j][k-1],g[i][j][k],INF);
     83                     add(f[i][j][k],f[i][j+(1<<k-1)][k-1],INF); add(g[i][j+(1<<k-1)][k-1],g[i][j][k],INF);
     84                     add(f[i][j][k],f[i+(1<<k-1)][j+(1<<k-1)][k-1],INF); add(g[i+(1<<k-1)][j+(1<<k-1)][k-1],g[i][j][k],INF);
     85                 }
     86     for (int i=1; i<=a; ++i)
     87     {
     88         scanf("%d%d%d%d%d",&w,&x,&y,&u,&v);
     89         add(s,++id_num,w);
     90         int k=LOG2[u-x+1];
     91         add(id_num,f[x][y][k],INF);
     92         add(id_num,f[x][v-(1<<k)+1][k],INF);
     93         add(id_num,f[u-(1<<k)+1][y][k],INF);
     94         add(id_num,f[u-(1<<k)+1][v-(1<<k)+1][k],INF);
     95     }
     96     
     97     for (int i=1; i<=b; ++i)
     98     {
     99         scanf("%d%d%d%d%d",&w,&x,&y,&u,&v);
    100         add(++id_num,t,w);
    101         int k=LOG2[u-x+1];
    102         add(g[x][y][k],id_num,INF);
    103         add(g[x][v-(1<<k)+1][k],id_num,INF);
    104         add(g[u-(1<<k)+1][y][k],id_num,INF);
    105         add(g[u-(1<<k)+1][v-(1<<k)+1][k],id_num,INF);
    106     }
    107     printf("%d
    ",Dinic(s,t));
    108 }
  • 相关阅读:
    LINUX下用select实现串口通讯示例
    续——老机焕发青春——win8 ramos 的本地安装 (涉及vhd差分盘)
    nexus 4 下 ubuntu touch 配置 nodejs环境
    nexus 4 下 DualBootInstallation 安装 ubuntu touch
    老机焕发青春 之硬盘篇
    Mac 10.9.2后airplay出现的bug
    初识javascript(一):js在windows下运行的几种形式
    过了一年了.关于扁平化.和一些唠叨
    inet_ntop(), inet_pton() inet_ntoa(), inet_aton(), inet_addr, htons(), htonl(), ntohs(), ntohl() struct hostent ,struct sockaddr_in
    gethostbyname尽量少用
  • 原文地址:https://www.cnblogs.com/refun/p/10630229.html
Copyright © 2011-2022 走看看