QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#476274#143. 最大流(随机数据)NOI_AK_ME#100 ✓3ms4120kbC++209.4kb2024-07-13 18:31:242024-07-13 18:31:24

Judging History

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

  • [2024-07-13 18:31:24]
  • 评测
  • 测评结果:100
  • 用时:3ms
  • 内存:4120kb
  • [2024-07-13 18:31:24]
  • 提交

answer

#include <algorithm>
#include <array>
#include <cassert>
#include <iostream>
#include <limits>
#include <numeric>
#include <queue>
#include <vector>
using namespace std;

inline char nc() {
  static char buf[100000], *p1, *p2;
  return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
             ? EOF
             : *p1++;
}
template <class T> inline void read(T &x) {
  x = 0;
  char c = nc();
  while (!isdigit(c))
    c = nc();
  while (isdigit(c))
    x = x * 10 + c - '0', c = nc();
}
template <typename T, typename... Args> inline void read(T &t, Args &...args) {
  read(t);
  read(args...);
}

using index_t = int;

namespace utils {

constexpr index_t LEN_INTERVAL = 7;
constexpr index_t INVALID_INDEX = -1;

class circular_link_list {
  const index_t num_vertex;
  std::vector<index_t> prev, next;
  index_t max_gap_h;

public:
  void reset() {
    max_gap_h = INVALID_INDEX;
    std::fill(prev.begin(), prev.begin() + num_vertex, INVALID_INDEX);
    std::iota(prev.begin() + num_vertex, prev.end(), num_vertex);
    std::fill(next.begin(), next.begin() + num_vertex, INVALID_INDEX);
    std::iota(next.begin() + num_vertex, next.end(), num_vertex);
  }

  bool only_one_node(const index_t h_u) const {
    return next[next[h_u + LEN_INTERVAL + num_vertex]] ==
           h_u + LEN_INTERVAL + num_vertex;
  }

  circular_link_list(const index_t _num_vertex)
      : num_vertex(_num_vertex),
        prev(2 * _num_vertex + LEN_INTERVAL + 1, INVALID_INDEX),
        next(2 * _num_vertex + LEN_INTERVAL + 1, INVALID_INDEX),
        max_gap_h(INVALID_INDEX) {
    std::iota(next.begin() + _num_vertex, next.end(), _num_vertex);
    std::iota(prev.begin() + _num_vertex, prev.end(), _num_vertex);
  };

  void insert(const index_t u, const index_t h_u) {
    if (h_u >= num_vertex + 1 || u >= num_vertex) {
      throw std::runtime_error("超过gap限制");
    }

    if (max_gap_h == INVALID_INDEX || max_gap_h < h_u) {
      max_gap_h = h_u;
    }

    next[u] = next[num_vertex + LEN_INTERVAL + h_u];
    prev[u] = num_vertex + LEN_INTERVAL + h_u;
    prev[next[num_vertex + LEN_INTERVAL + h_u]] = u;
    next[num_vertex + LEN_INTERVAL + h_u] = u;
  }

  void remove(const index_t u) {
    if (u >= num_vertex || next[u] == INVALID_INDEX ||
        prev[u] == INVALID_INDEX) {
      return;
    }
    prev[next[u]] = prev[u];
    next[prev[u]] = next[u];
    next[u] = INVALID_INDEX;
    prev[u] = INVALID_INDEX;
  }

  void refresh_height(index_t *const h_arr, const index_t old_h) {
    for (index_t h = old_h; h <= max_gap_h; h++) {
      index_t first_node = next[h + LEN_INTERVAL + num_vertex];
      for (index_t u = first_node; u < num_vertex; u = next[u]) {
        h_arr[u] = num_vertex + 1;
      }
      while (first_node < num_vertex) {
        index_t to_del = first_node;
        first_node = next[first_node];
        next[to_del] = INVALID_INDEX;
        prev[to_del] = INVALID_INDEX;
      }
      next[h + LEN_INTERVAL + num_vertex] = h + LEN_INTERVAL + num_vertex;
      prev[h + LEN_INTERVAL + num_vertex] = h + LEN_INTERVAL + num_vertex;
    }
    max_gap_h = old_h - 1;
  }
};

class height_queue {
  std::vector<index_t> height_bone;
  std::vector<index_t> next;
  index_t max_h;

public:
  void reset() {
    std::fill(height_bone.begin(), height_bone.end(), INVALID_INDEX);
    std::fill(next.begin(), next.end(), INVALID_INDEX);
    max_h = INVALID_INDEX;
  }

  height_queue(const index_t num_vertex)
      : height_bone(2 * num_vertex, INVALID_INDEX),
        next(num_vertex + 1, INVALID_INDEX), max_h(INVALID_INDEX) {}

  index_t dequeue() {
    while (max_h != INVALID_INDEX && height_bone[max_h] == INVALID_INDEX) {
      max_h--;
    }
    if (max_h == INVALID_INDEX) {
      return INVALID_INDEX;
    }
    index_t to_del = height_bone[max_h];
    height_bone[max_h] = next[to_del];
    return to_del;
  }

  void enqueue(const index_t u, const index_t h_u) {
    if (u >= next.size()) {
      throw std::runtime_error("enqueue 节点编号越界");
    }
    if (h_u >= height_bone.size()) {
      throw std::runtime_error("enqueue 节点高度越界");
    }

    next[u] = height_bone[h_u];
    height_bone[h_u] = u;

    if (max_h == INVALID_INDEX || h_u > max_h) {
      max_h = h_u;
    }
  }
};

}

constexpr index_t MAXN = 1200 + 5;

using flow_amount_t = long long int;

struct HLPP {
  const flow_amount_t INF = numeric_limits<flow_amount_t>::max();
  struct edge {
    index_t to, rev;
    flow_amount_t f;
  };

  index_t maxn, s, t;

  std::vector<edge> edges;
  std::vector<index_t> first_edge;

  utils::height_queue h_que;

  flow_amount_t excess[MAXN];
  std::vector<index_t> arc;

  utils::circular_link_list gap_list;

  std::vector<index_t> height;
  index_t work;


  HLPP(vector<index_t> degrees, index_t s, index_t t)
      : h_que(degrees.size() + 1), gap_list(degrees.size()) {
    this->s = s;
    this->t = t;
    maxn = degrees.size();
    first_edge = std::vector<index_t>(maxn + 1);

    height = std::vector<index_t>(maxn + 1);
    assert(maxn <= MAXN);
    index_t cnt = 0;
    for (index_t i = 0; i < maxn; ++i) {
      first_edge[i] = cnt;
      cnt += degrees[i];
    }
    first_edge[maxn] = cnt;
    edges = std::vector<edge>(cnt);
  }

  void show_all() const {
    for (index_t u = 0; u < maxn; u++) {
      printf("节点%d 🌊%d:[", u + 1, height[u]);
      for (index_t k = first_edge[u]; k < first_edge[u + 1]; k++) {
        printf("🥝%d(%lld) ", edges[k].to + 1, edges[k].f);
      }
      std::cout << ']' << std::endl;
    }
  }

  void addEdge(index_t from, index_t to, flow_amount_t f) {
    static std::vector<index_t> _cur_edge(first_edge);
    edges[_cur_edge[from]] = {to, _cur_edge[to], f};
    edges[_cur_edge[to]] = {from, _cur_edge[from], 0};
    _cur_edge[to]++;
    _cur_edge[from]++;
  }



  void updHeight(index_t v, index_t nh) {
    if (height[v] != maxn) {
      gap_list.remove(v);
    }

    height[v] = nh;
    if (nh == maxn)
      return;

    if (excess[v] > 0) {
      h_que.enqueue(v, nh);
    }

    if (v != s && v != t) {
      gap_list.insert(v, height[v]);
    }
  }

  void globalRelabel() {
    work = 0;
    fill(height.begin(), height.end(), maxn);
    h_que.reset();
    gap_list.reset();
    height[t] = 0;
    std::queue<index_t> que;
    que.push(t);

    while (que.empty() == false) {
      index_t v = que.front();
      que.pop();
      for (index_t ie = first_edge[v]; ie < first_edge[v + 1]; ++ie) {
        auto &e = edges[ie];
        if (height[e.to] == maxn && edges[e.rev].f > 0) {
          que.push(e.to);
          updHeight(e.to, height[v] + 1);
        }
      }
    }
    height[s] = maxn;
  }

  void push(index_t v, edge &e) {
    flow_amount_t df = min(excess[v], e.f);
    if (df > 0) {
      if (excess[e.to] == 0) {
        h_que.enqueue(e.to, height[e.to]);
      }

      e.f -= df, edges[e.rev].f += df;
      excess[v] -= df, excess[e.to] += df;
    }
  }

  void discharge(index_t v) {
    index_t nh = maxn;

    for (index_t i = arc[v]; i < first_edge[v + 1]; i++) {
      auto &e = edges[i];
      if (e.f > 0) {
        if (height[v] == height[e.to] + 1) {
          push(v, e);
          if (excess[v] <= 0) {
            arc[v] = i;
            return;
          }
        } else
          nh = min(nh, height[e.to] + 1);
      }
    }

    for (index_t i = first_edge[v]; i < arc[v]; i++) {
      auto &e = edges[i];
      if (e.f > 0) {
        if (height[v] == height[e.to] + 1) {
          push(v, e);
          if (excess[v] <= 0) {
            arc[v] = i;
            return;
          }
        } else
          nh = min(nh, height[e.to] + 1);
      }
    }

    work++;

    if (gap_list.only_one_node(height[v]) == false) {
      updHeight(v, nh);
    } else {
      gap_list.refresh_height(height.data(), height[v]);

    }
  }

  flow_amount_t calc() {
    for (index_t v = 0; v < maxn; ++v) {
      sort(edges.begin() + first_edge[v], edges.begin() + first_edge[v + 1],
           [](edge &l, edge &r) { return l.to < r.to; });
      for (index_t i = first_edge[v]; i < first_edge[v + 1]; i++) {
        auto &e = edges[i];
        edges[e.rev].rev = i;
      }
    }

    arc = first_edge;
    arc.pop_back();
    fill(excess, excess + maxn, 0);
    excess[s] = INF, excess[t] = -INF;
    globalRelabel();

    for (index_t ie = first_edge[s]; ie < first_edge[s + 1]; ie++)
      push(s, edges[ie]);

    for (index_t u = h_que.dequeue(); u != utils::INVALID_INDEX;
         u = h_que.dequeue()) {
      if (u == s || u == t) {
        continue;
      }
      discharge(u);
      if (work > 4 * maxn)
        globalRelabel();
    }



    return excess[t] + INF;
  }
};

int main(void) {
  index_t n, m, s, t;
  read(n, m, s, t);
  s--;
  t--;
  vector<array<index_t, 3>> input_data;
  input_data.reserve(m);
  vector<index_t> degs(n);
  for (index_t xxx = 1; xxx <= m; xxx++) {
    std::array<index_t, 3> x{};
    read(x[0], x[1], x[2]);
    if (x[0] == x[1]) {
      continue;
    }
    x[0]--, x[1]--;
    ++degs[x[0]];
    ++degs[x[1]];
    input_data.push_back(x);
  }
  HLPP hlpp(degs, s, t);
  for (auto &x : input_data)
    hlpp.addEdge(x[0], x[1], x[2]);
  printf("%lld\n", hlpp.calc());
  return 0;
}

詳細信息

Test #1:

score: 12.5
Accepted
time: 0ms
memory: 3756kb

input:

52 275 1 2
11 18 1
18 48 9
10 15 1
11 19 1
10 20 1
3 14 1
8 16 1
31 32 2147483647
10 42 9
5 14 1
3 15 1
5 17 1
6 50 9
1 6 9
28 29 2147483647
18 40 9
43 42 2147483647
1 9 9
9 20 1
1 7 9
24 6 9
39 38 2147483647
4 14 1
38 37 2147483647
5 46 9
3 18 1
15 44 9
4 17 1
32 33 2147483647
28 9 9
32 9 9
26 12 9...

output:

729

result:

ok single line: '729'

Test #2:

score: 12.5
Accepted
time: 1ms
memory: 4120kb

input:

67 4489 14 1
25 63 19983
49 18 26963
9 29 23009
25 30 10286
45 6 14693
61 11 8464
12 19 29821
39 36 2365
12 7 20737
56 51 21002
9 63 14701
15 10 24386
21 36 25930
49 21 10680
56 11 25508
26 27 2101
46 4 1770
16 56 19722
23 8 28411
67 32 28897
45 62 22880
30 38 13226
37 56 18650
10 57 700
62 53 19659...

output:

1025243

result:

ok single line: '1025243'

Test #3:

score: 12.5
Accepted
time: 1ms
memory: 3792kb

input:

100 1029 1 2
39 96 19
68 19 19
16 33 1
17 25 1
74 22 19
50 23 19
46 29 19
70 24 19
27 92 19
50 25 19
6 36 1
34 80 19
72 19 19
48 13 19
11 86 19
19 86 19
100 99 2147483647
4 39 1
60 9 19
76 7 19
34 100 19
98 97 2147483647
15 25 1
14 94 19
5 40 1
4 38 1
46 34 19
90 89 2147483647
42 39 19
58 27 19
3 39...

output:

4693

result:

ok single line: '4693'

Test #4:

score: 12.5
Accepted
time: 0ms
memory: 4032kb

input:

100 500 64 68
97 1 597234350
42 59 1020828575
52 59 1341185789
46 82 534859215
84 98 1408384018
95 85 97421544
50 51 1658946459
71 91 1071433566
16 5 577259372
79 16 941940144
32 66 2144021311
42 94 132280559
100 83 2093384600
34 98 1633024304
31 69 735801701
68 13 632197336
70 25 868338831
60 91 14...

output:

4259958644

result:

ok single line: '4259958644'

Test #5:

score: 12.5
Accepted
time: 1ms
memory: 3868kb

input:

100 1500 30 87
12 52 1212854316
66 34 500229329
28 30 1905848380
45 10 1906211267
35 5 1227091997
14 10 797678626
42 39 2119948760
80 55 263028757
72 32 1402091192
2 70 114204531
53 87 1885940117
39 68 1262963681
20 100 363298998
81 19 475298425
86 17 276841422
95 43 940479356
85 55 1720319570
40 65...

output:

17139501202

result:

ok single line: '17139501202'

Test #6:

score: 12.5
Accepted
time: 1ms
memory: 3884kb

input:

100 5000 12 73
5 90 596775756
35 20 226786760
28 31 1775982092
79 17 743002845
10 19 150120683
83 96 901953035
91 62 809520329
2 61 1024423315
30 91 1374494188
93 26 751944004
82 82 727762428
1 43 502389284
84 87 1379778919
52 32 1459460146
71 15 983677176
18 3 249963037
80 32 828290820
40 99 159181...

output:

37381805875

result:

ok single line: '37381805875'

Test #7:

score: 12.5
Accepted
time: 3ms
memory: 3920kb

input:

100 5000 13 28
74 16 599476
99 76 112185
76 68 887056
13 2 181381
23 72 214611
10 15 955272
57 53 163306
81 44 721618
68 62 71172
70 44 233121
13 52 701794
77 40 298244
54 28 626039
26 63 829000
25 14 91588
97 62 980457
17 15 572847
100 75 273645
4 65 344467
17 47 299474
40 19 270752
50 68 804106
21...

output:

2193636882

result:

ok single line: '2193636882'

Test #8:

score: 12.5
Accepted
time: 2ms
memory: 3928kb

input:

100 5000 66 90
35 39 966842
3 56 577708
38 60 515530
3 73 351251
29 27 508007
56 70 185615
73 51 331650
6 32 589603
29 96 822851
9 99 335209
20 45 806531
60 10 460779
93 21 203582
77 27 391590
3 14 315530
86 41 234991
53 69 96865
97 15 203159
14 43 815111
4 24 337097
88 79 288209
64 34 806690
13 26 ...

output:

4340954172

result:

ok single line: '4340954172'