[BZOJ1066][SCOI2007]蜥蜴[最大流]

每个柱子拆成两个点 连一条柱子高度的边限流

源点->蜥蜴->汇点 或者 源点->蜥蜴->拆成的第一个点->拆成的第二个点->汇点

细节多

#include <bits/stdc++.h>
using namespace std;
 
const int MAXN = 1207;
const int MAXM = 2e5+7;
const int inf = 0x3f3f3f3f-1;
char mat1[24][25], mat2[24][25];
int head[MAXN], dep[MAXN], tot = 1, cur[MAXN], maxflow;
int n, m, a, b, tmp, s, t, d;
struct Edge {
  int v, w, next;
} G[MAXM<<1];
 
inline void add(int u, int v, int w) {
  G[++tot] = (Edge) {v, w, head[u]};head[u] = tot;
  G[++tot] = (Edge) {u, 0, head[v]};head[v] = tot;
}
 
bool bfs(int s, int t) {
  memset(dep, 0x3f, sizeof dep);
  memcpy(cur, head, sizeof head);
  queue<int>q;
  while(!q.empty()) q.pop();
  dep[s] = 0;
  q.push(s);
  while(!q.empty()) {
    int u = q.front();
    q.pop();
    for(int i = head[u]; i; i = G[i].next) {
      int v = G[i].v, w = G[i].w;
      if (dep[v] > inf && w) {
        dep[v] = dep[u] + 1;
        if (v == t) return 1;
        q.push(v);
      }
    }
  }
  return dep[t] < inf;
}
 
int dfs(int u, int t, int limit) {
  if (u == t || !limit) return limit;
  int flow = 0, f;
  for(int i = cur[u]; i; i = G[i].next) {
    cur[u] = i;
    int v = G[i].v, w = G[i].w;
    if (dep[v] == dep[u] + 1 && (f = dfs(v, t, min(w, limit)))) {
      flow += f;
      limit -= f;
      G[i].w -= f;
      G[i^1].w += f;
      if (!limit) break;
    }
  }
  return flow;
}
 
 
inline int get(int x, int y) {
  return (x-1)*b + y;
}
void dinic(int s, int t) {
  while(bfs(s, t)) maxflow += dfs(s, t, inf);
}
 
inline bool ok(int x, int y, int xx, int yy) {
  return ((x-xx)*(x-xx)+(y-yy)*(y-yy)<=(d*d) && mat1[x][y] > '0' && mat1[xx][yy] > '0');
}
int ans;
int Get[105][105];
int main(void) {
  scanf("%d%d%d", &a, &b, &d);
  n = a*b*2; s = n+1, t = n+2;
  for(int i = 1; i <= a; ++i) scanf("%s", mat1[i]+1);
  for(int i = 1; i <= a; ++i) scanf("%s", mat2[i]+1);
  for(int i = 1; i <= a; ++i)
    for(int j = 1; j <= b; ++j) {
      if (mat1[i][j] - '0') add(get(i,j), get(i,j) + a*b, mat1[i][j] - '0');
      if (mat2[i][j] == 'L') ++ans, add(s, get(i,j), 1);
    }
  for(int i = 1; i <= a; ++i)
    for(int j = 1; j <= b; ++j) {
      if (min(a - i + 1, i) <= d || min(b - j + 1, j) <= d) add(get(i,j)+a*b, t, inf);
    }
  for(int i = 1; i <= a; ++i)
    for(int j = 1; j <= b; ++j)
      for(int k = 1; k <= a; ++k)
        for(int l = 1; l <= b; ++l) {
          if (ok(i,j,k,l)) add(get(i,j) + a*b, get(k,l), inf);
        }
  dinic(s, t);
  cout << ans-maxflow << endl;
  return 0;
}

posted @ 2018-12-28 16:45  QvvQ  阅读(112)  评论(0编辑  收藏