[HDU2389] Rain on your Parade

2017年10月11日

题意:还有 t 分钟就要下雨了,每个人回家可以先去拿伞,不然要被淋。现在知道每个人的坐标以及行走速度,还有伞的位置坐标。问你最多有多少人不会被雨淋到。

如果用匈牙利算法做这个题会超时,得用 Hopcroft-Carp算法。
匈牙利算法时间复杂度是 $$O(VE)$$,而 Hopcroft-Carp算法是 $$O(\\sqrt V E)$$,可见后者更适合处理大数据。

Hopcroft-Carp算法主要是对匈牙利算法的优化,在寻找增广路径的时候同时寻找多条不相交的增广路径,形成极大路径集。然后对极大增广路径集进行增广。在寻找增广路径集的每个阶段,找到的增广路径集都具有相同的长度,且随着算法的进行,增广路径的长度不断的扩大。可以证明,最多增广$$\\sqrt V $$次就可以得到最大匹配。

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 3005;
struct people {
  int x, y, v;
}e[N];
struct umbrella {
  int x, y;
}u[N];
int n, m, t;
int xlink[N], ylink[N], dx[N], dy[N], vis[N];
int dis;
vector<int> G[N];
bool bfs()
{
  memset(dx, -1, sizeof(dx));
  memset(dy, -1, sizeof(dy));
  dis = INF;
  queue<int> que;
  for (int i = 0; i < n; i++) {
    if (xlink[i] == -1) {
      dx[i] = 0;
      que.push(i);
    }
  }
  while (!que.empty()) {
    int u = que.front();
    que.pop();
    if (dx[u] > dis)
      break;
    for (int i = 0; i < G[u].size(); i++) {
      int v = G[u][i];
      if (dy[v] == -1) {
        dy[v] = dx[u] + 1;
        if (ylink[v] == -1) {
          dis = dy[v];
        } else {
          dx[ylink[v]] = dy[v] + 1;
          que.push(ylink[v]);
        }
      }
    }
  }
  return dis != INF;
}
int dfs(int u)
{
  for (int i = 0; i < G[u].size(); i++) {
    int v = G[u][i];
    if (!vis[v] && dy[v] == dx[u] + 1) {
      vis[v] = 1;
      if (ylink[v] != -1 && dis == dy[v])
        continue;
      if (ylink[v] == -1 || dfs(ylink[v])) {
        ylink[v] = u;
        xlink[u] = v;
        return 1;
      }
    }
  }
  return 0;
}
int max_match()
{
  int res = 0;
  memset(xlink, -1, sizeof(xlink));
  memset(ylink, -1, sizeof(ylink));
  while (bfs()) {
    memset(vis, 0, sizeof(vis));
    for (int i = 0; i < n; i++) {
      if (xlink[i] == -1) {
        res += dfs(i);
      }
    }
  }
  return res;
}
int main()
{
  int tt;
  scanf("%d", &tt);
  for (int cas = 1; cas <= tt; cas++) {
    scanf("%d %d", &t, &m);
    for (int i = 0; i < m; i++) {
      scanf("%d %d %d", &e[i].x, &e[i].y, &e[i].v);
    }
    scanf("%d", &n);
    for (int j = 0; j < n; j++) {
      G[j].clear();
      scanf("%d %d", &u[j].x, &u[j].y);
      for (int i = 0; i < m; i++) {
        double dis = sqrt(1.0 * ((e[i].x - u[j].x) * (e[i].x - u[j].x) + (e[i].y - u[j].y) * (e[i].y - u[j].y)));
        if (dis <= 1.0 * e[i].v * t) {
          G[j].push_back(i);
        }
      }
    }
    int ans = max_match();
    printf("Scenario #%d:\n%d\n\n", cas, ans);
  }
  return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注