QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#277425#6570. Who Watches the Watchmen?ucup-team1198#WA 711ms3764kbC++148.0kb2023-12-06 18:49:432023-12-06 18:49:43

Judging History

你现在查看的是最新测评结果

  • [2023-12-06 18:49:43]
  • 评测
  • 测评结果:WA
  • 用时:711ms
  • 内存:3764kb
  • [2023-12-06 18:49:43]
  • 提交

answer

#include <map>
#include <set>
#include <array>
#include <cmath>
#include <deque>
#include <bitset>
#include <random>
#include <string>
#include <vector>
#include <cassert>
#include <complex>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>

using namespace std;

#define int int64_t

struct Vector {
  int x;
  int y;
  int z;

  Vector(int x = 0, int y = 0, int z = 0): x(x), y(y), z(z) {}
  Vector(const Vector& a, const Vector& b): x(b.x - a.x), y(b.y - a.y), z(b.z - a.z) {}
};

Vector operator-(const Vector& a, const Vector& b) {
  return Vector(b, a);
}

Vector operator+(const Vector& a, const Vector& b) {
  return {a.x + b.x, a.y + b.y, a.z + b.z};
}

int operator*(const Vector& a, const Vector& b) {
  return a.x * b.x + a.y * b.y + a.z * b.z;
}

__int128 dot(const Vector& a, const Vector& b) {
  return (__int128)a.x * b.x + (__int128)a.y * b.y + (__int128)a.z * b.z;
}

Vector operator%(const Vector& a, const Vector& b) {
  return Vector(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
}

int vol(const Vector& a, const Vector& b, const Vector& c) {
  return a * (b % c);
}

__int128 vol128(const Vector& a, const Vector& b, const Vector& c) {
  return  dot(a, (b % c));
}

istream& operator>>(istream& in, Vector& v) {
  in >> v.x >> v.y >> v.z;
  return in;
}

bool operator==(const Vector& a, const Vector& b) {
  return a.x == b.x && a.y == b.y && a.z == b.z;
}

bool coplane(const Vector& a, const Vector& b, const Vector& c, const Vector& d) {
  return vol(b - a, c - a, d - a) == 0;
}

const int MAXN = 600;
Vector p[MAXN], dir[MAXN];

struct CostEdge {
  int from, to, cap, cost, nxt;
  int flow = 0;
  CostEdge() {}
  CostEdge(int from, int to, int cap, int cost, int nxt): from(from), to(to), cap(cap), cost(cost), nxt(nxt) {}
};

struct CostFlow {
  static constexpr int INF = 1e9;

  int n;
  int s, t;
  vector<CostEdge> e;
  vector<int> head;

  CostFlow(int n, int s = -1, int t = -1): n(n), s(s), t(t), head(vector<int>(n, -1)) {}

  void add_edge(int from, int to, int cap, int cost) {
    /// cerr << from << " " << to << " " << cap << " " << cost << endl;
    e.emplace_back(from, to, cap, cost, head[from]);
    head[from] = e.size() - 1;
    e.emplace_back(to, from, 0, -cost, head[to]);
    head[to] = e.size() - 1;
  }

  vector<int> pot;
  int cost = 0;
  int flow = 0;

  void calc_pot() {
    pot = vector<int>(n, INF);
    pot[s] = 0;
    for (int i = 0; i < n; ++i) {
      for (auto e1 : e) {
        if (e1.flow < e1.cap) {
          pot[e1.to] = min(pot[e1.to], pot[e1.from] + e1.cost);
        }
      }
    }
  }

  bool step() {
    vector<int> dist(n, INF);
    vector<int> pred(n, -1);
    vector<int> used(n, 0);
    dist[s] = 0;
    while (true) {
      int v = -1;
      for (int i = 0; i < n; ++i) {
        if (used[i]) continue;
        if (v == -1 || dist[i] < dist[v]) {
          v = i;
        }
      }
      if (v == -1) break;
      used[v] = true;
      for (int i = head[v]; i != -1; i = e[i].nxt) {
        if (e[i].flow == e[i].cap) continue;
        if (dist[e[i].to] > dist[v] + e[i].cost + pot[v] - pot[e[i].to]) {
          dist[e[i].to] = dist[v] + e[i].cost + pot[v] - pot[e[i].to];
          pred[e[i].to] = i;
        }
      }
    }

    /**for (int i = 0; i < n; ++i) {
      cerr << dist[i] << " ";
    }
    cerr << endl;*/

    if (dist[t] == INF) return false;
    int mn = INF;
    int at = t;
    int pr = pred[at];
    while (pr != -1) {
      mn = min(mn, e[pr].cap - e[pr].flow);
      at = e[pr].from;
      pr = pred[at];
    }

    at = t;
    pr = pred[at];
    while (pr != -1) {
      e[pr].flow += mn;
      e[pr ^ 1].flow -= mn;
      at = e[pr].from;
      pr = pred[at];
    }

    flow += mn;
    cost += mn * (dist[t] + pot[t]);

    for (int i = 0; i < n; ++i) {
      pot[i] += dist[i];
    }
    return true;
  }

  pair<int, int> get() {
    calc_pot();
    while (step()) {
      /// cerr << "step" << endl;
    }
    return {flow, cost};
  }
};

signed main() {
#ifdef DEBUG
  freopen("input.txt", "r", stdin);
  freopen("output.txt", "w", stdout);
#else
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
#endif

  int n;
  cin >> n;
  for (int i = 0; i < n; ++i) {
    cin >> p[i] >> dir[i];
  }

  if (n == 1) {
    cout << "-1\n";
    return 0;
  }

  bool is_col = (n % 2 != 0);
  for (int i = 2; i < n; ++i) {
    is_col &= ((p[i] - p[0]) % (p[1] - p[0]) == Vector());
  }

  if (is_col) {
    int ans = 2000;
    Vector start = p[0];
    Vector go = p[1] - p[0];
    vector<int> ord(n);
    iota(ord.begin(), ord.end(), 0);
    sort(ord.begin(), ord.end(), [&](int i, int j) {
      return (p[i] - start) * go < (p[j] - start) * go;
    });
    for (int i = 0; i < n; ++i) {
      vector<int> lft;
      for (int j = 0; j < n; ++j) {
        if (j != i) {
          lft.push_back(j);
        }
      }
      int cnt = 0;
      for (int i = 0; i < n - 2; ++i) {
        if (dir[ord[lft[i]]] % go == Vector() && dir[ord[lft[i]]] * go > 0) {

        } else {
          ++cnt;
        }
      }
      int start = ord[lft[0]];
      int fin = ord[lft[n - 2]];
      int ind = ord[i];
      if (dir[ind] % go == Vector() && dir[fin] % go == Vector()) {
        cnt += 2;
      } else if (dir[ind] % go == Vector() || dir[fin] % go == Vector()) {
        ++cnt;
      } else {
        if (!coplane(p[start], p[fin], p[fin] + dir[fin], p[start] - dir[ind])) {
          ++cnt;
        } else if (dir[fin] % dir[ind] == Vector()) {
          ++cnt;
        } else {
          Vector norm = go % dir[ind];
          __int128 a = vol128(norm, go, dir[fin]);
          __int128 b = vol128(norm, go, dir[ind]);
          if (a < 0 && b < 0) {
            ++cnt;
          } else if (a > 0 && b > 0) {
            ++cnt;
          }
        }
      }
      ans = min(ans, cnt + 1000);

      cnt = 0;
      for (int i = 1; i < n - 1; ++i) {
        if (dir[ord[lft[i]]] % go == Vector() && dir[ord[lft[i]]] * go < 0) {

        } else {
          ++cnt;
        }
      }
      start = ord[lft[n - 2]];
      fin = ord[lft[0]];
      ind = ord[i];
      if (dir[ind] % go == Vector() && dir[fin] % go == Vector()) {
        cnt += 2;
      } else if (dir[ind] % go == Vector() || dir[fin] % go == Vector()) {
        ++cnt;
      } else {
        if (!coplane(p[start], p[fin], p[fin] + dir[fin], p[start] - dir[ind])) {
          ++cnt;
        } else if (dir[fin] % dir[ind] == Vector()) {
          ++cnt;
        } else {
          Vector norm = go % dir[ind];
          __int128 a = vol128(norm, go, dir[fin]);
          __int128 b = vol128(norm, go, dir[ind]);
          if (a < 0 && b < 0) {
            ++cnt;
          } else if (a > 0 && b > 0) {
            ++cnt;
          }
        }
      }
      ans = min(ans, cnt + 1000);
    }
    cout << ans << "\n";
    return 0;
  }

  CostFlow mincost(2 * n + 2, 2 * n, 2 * n + 1);
  for (int i = 0; i < n; ++i) {
    mincost.add_edge(2 * i + 1, 2 * i, 1, 1000);
    mincost.add_edge(mincost.s, 2 * i + 1, 1, 0);
    mincost.add_edge(2 * i, mincost.t, 1, 0);
  }

  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (i == j) continue;
      bool has_veiw = true;
      for (int k = 0; k < n; ++k) {
        if (k == i || k == j) continue;
        if ((p[k] - p[i]) % (p[j] - p[i]) == Vector()) {
          if ((p[i] - p[k]) * (p[j] - p[k]) < 0) {
            has_veiw = false;
            break;
          }
        }
      }
      if (!has_veiw) continue;
      int cost = 1;
      if (dir[i] % (p[j] - p[i]) == Vector() && dir[i] * (p[j] - p[i]) > 0) {
        cost = 0;
      }
      mincost.add_edge(2 * i + 1, 2 * j, 1, cost);
    }
  }

  /// cerr << "start mincost" << endl;

  auto res = mincost.get();
  /// cerr << res.first << endl;
  assert(res.first == n);
  cout << res.second << "\n";
  
  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 3476kb

input:

7
0 0 0 1 0 0
1 0 0 -1 0 0
2 0 0 1 0 0
3 0 0 1 0 0
4 0 0 1 0 0
5 0 0 1 0 0
6 0 0 -1 0 0

output:

1002

result:

ok single line: '1002'

Test #2:

score: 0
Accepted
time: 0ms
memory: 3488kb

input:

4
66 45 10 73 39 36
95 14 26 47 84 59
14 66 89 89 36 78
16 27 94 79 24 24

output:

4

result:

ok single line: '4'

Test #3:

score: 0
Accepted
time: 0ms
memory: 3484kb

input:

3
0 0 0 1 0 0
1 1 1 1 0 0
2 2 2 1 0 0

output:

1002

result:

ok single line: '1002'

Test #4:

score: 0
Accepted
time: 0ms
memory: 3532kb

input:

3
0 0 0 1 1 1
1 1 1 1 0 0
2 2 2 1 0 0

output:

1001

result:

ok single line: '1001'

Test #5:

score: 0
Accepted
time: 1ms
memory: 3596kb

input:

3
0 0 0 1 0 0
1 1 1 1 0 0
2 2 2 -1 -1 -1

output:

1001

result:

ok single line: '1001'

Test #6:

score: 0
Accepted
time: 1ms
memory: 3476kb

input:

3
0 0 0 1 0 0
1 1 1 1 2 2
2 2 2 -1 -1 -1

output:

1000

result:

ok single line: '1000'

Test #7:

score: 0
Accepted
time: 0ms
memory: 3492kb

input:

3
0 0 0 1 0 0
1 1 1 1 2 2
2 2 2 1 1 1

output:

1001

result:

ok single line: '1001'

Test #8:

score: 0
Accepted
time: 0ms
memory: 3528kb

input:

1
0 0 0 3 1 4

output:

-1

result:

ok single line: '-1'

Test #9:

score: 0
Accepted
time: 0ms
memory: 3568kb

input:

4
0 0 0 1 1 1
1 0 0 -1 0 0
1 1 1 0 -1 0
1 0 1 0 1 0

output:

1

result:

ok single line: '1'

Test #10:

score: 0
Accepted
time: 706ms
memory: 3764kb

input:

500
0 0 0 1 0 0
1 0 0 1 0 0
2 0 0 -1 0 0
3 0 0 1 0 0
4 0 0 1 0 0
5 0 0 1 0 0
6 0 0 1 0 0
7 0 0 1 0 0
8 0 0 1 0 0
9 0 0 1 0 0
10 0 0 -1 0 0
11 0 0 -1 0 0
12 0 0 1 0 0
13 0 0 -1 0 0
14 0 0 1 0 0
15 0 0 1 0 0
16 0 0 1 0 0
17 0 0 -1 0 0
18 0 0 -1 0 0
19 0 0 -1 0 0
20 0 0 -1 0 0
21 0 0 1 0 0
22 0 0 1 0 0...

output:

250

result:

ok single line: '250'

Test #11:

score: 0
Accepted
time: 711ms
memory: 3748kb

input:

500
0 0 0 0 1 0
0 1 0 0 1 0
0 2 0 0 -1 0
0 3 0 0 1 0
0 4 0 0 1 0
0 5 0 0 1 0
0 6 0 0 1 0
0 7 0 0 1 0
0 8 0 0 1 0
0 9 0 0 1 0
0 10 0 0 -1 0
0 11 0 0 -1 0
0 12 0 0 1 0
0 13 0 0 -1 0
0 14 0 0 1 0
0 15 0 0 1 0
0 16 0 0 1 0
0 17 0 0 -1 0
0 18 0 0 -1 0
0 19 0 0 -1 0
0 20 0 0 -1 0
0 21 0 0 1 0
0 22 0 0 1 0...

output:

250

result:

ok single line: '250'

Test #12:

score: 0
Accepted
time: 710ms
memory: 3760kb

input:

500
0 0 0 0 0 1
0 0 1 0 0 1
0 0 2 0 0 -1
0 0 3 0 0 1
0 0 4 0 0 1
0 0 5 0 0 1
0 0 6 0 0 1
0 0 7 0 0 1
0 0 8 0 0 1
0 0 9 0 0 1
0 0 10 0 0 -1
0 0 11 0 0 -1
0 0 12 0 0 1
0 0 13 0 0 -1
0 0 14 0 0 1
0 0 15 0 0 1
0 0 16 0 0 1
0 0 17 0 0 -1
0 0 18 0 0 -1
0 0 19 0 0 -1
0 0 20 0 0 -1
0 0 21 0 0 1
0 0 22 0 0 1...

output:

250

result:

ok single line: '250'

Test #13:

score: 0
Accepted
time: 1ms
memory: 3552kb

input:

5
1 0 0 1 -1 0
2 0 0 0 1 0
3 0 0 -1 0 0
4 0 0 -1 0 0
5 0 0 -1 0 0

output:

1000

result:

ok single line: '1000'

Test #14:

score: 0
Accepted
time: 0ms
memory: 3480kb

input:

5
1 0 0 1 0 0
2 0 0 1 0 0
3 0 0 1 0 0
4 0 0 0 1 0
5 0 0 -1 -1 0

output:

1000

result:

ok single line: '1000'

Test #15:

score: 0
Accepted
time: 0ms
memory: 3492kb

input:

6
0 1 0 1 0 0
0 2 0 0 2 0
0 3 0 0 3 0
0 4 0 0 4 0
0 5 0 0 5 0
0 6 0 0 6 0

output:

4

result:

ok single line: '4'

Test #16:

score: 0
Accepted
time: 0ms
memory: 3504kb

input:

9
1 0 0 1 0 0
2 0 0 1 0 0
3 0 0 1 0 0
0 1 0 0 1 0
0 2 0 0 1 0
0 3 0 0 1 0
0 0 1 0 0 1
0 0 2 0 0 1
0 0 3 0 0 1

output:

3

result:

ok single line: '3'

Test #17:

score: -100
Wrong Answer
time: 3ms
memory: 3572kb

input:

499
0 0 0 1 0 0
1 0 0 1 0 0
2 0 0 -1 0 0
3 0 0 1 0 0
4 0 0 1 0 0
5 0 0 1 0 0
6 0 0 1 0 0
7 0 0 1 0 0
8 0 0 1 0 0
9 0 0 1 0 0
10 0 0 -1 0 0
11 0 0 -1 0 0
12 0 0 1 0 0
13 0 0 -1 0 0
14 0 0 1 0 0
15 0 0 1 0 0
16 0 0 1 0 0
17 0 0 -1 0 0
18 0 0 -1 0 0
19 0 0 -1 0 0
20 0 0 -1 0 0
21 0 0 1 0 0
22 0 0 1 0 0...

output:

1242

result:

wrong answer 1st lines differ - expected: '1220', found: '1242'