QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#519813#5670. Group Guestsucup-team1198WA 367ms201840kbC++209.8kb2024-08-15 03:09:592024-08-15 03:09:59

Judging History

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

  • [2024-08-15 03:09:59]
  • 评测
  • 测评结果:WA
  • 用时:367ms
  • 内存:201840kb
  • [2024-08-15 03:09:59]
  • 提交

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;

const int MAXN = 4'000'100;
vector<pair<int, int>> G[MAXN];
int tin[MAXN];
int tup[MAXN];
int ttime = 0;

vector<int> stack;
vector<vector<int>> edge_comps;
int edge_comp_id[MAXN];

int used[MAXN];
vector<int> vertices;

void dfs_dot(int v, int p) {
  vertices.emplace_back(v);
  tin[v] = ttime;
  tup[v] = ttime;
  ++ttime;
  used[v] = 1;
  for (auto [u, i] : G[v]) {
    if (i == p)
      continue;
    if (used[u] == 0) {
      int stack_sz = stack.size();
      stack.emplace_back(i);
      dfs_dot(u, i);
      if (tup[u] >= tin[v]) {
        // falls off
        edge_comps.emplace_back();
        while (stack.size() > stack_sz) {
          edge_comps.back().emplace_back(stack.back());
          stack.pop_back();
        }
      }
      tup[v] = min(tup[v], tup[u]);
    } else if (used[u] == 1) {
      // edge up
      stack.emplace_back(i);
      tup[v] = min(tup[v], tin[u]);
    } else {
      // not interesting
    }
  }
  used[v] = 2;
}

vector<int> Gtree[MAXN];
int up[MAXN];
int tree_sz[MAXN];

void dfs_tree(int v, int p) {
  up[v] = p;
  for (int u : Gtree[v]) {
    if (u == p)
      continue;
    dfs_tree(u, v);
    tree_sz[v] += tree_sz[u];
  }
}

int id[MAXN];
vector<pair<int, int>> Gright[MAXN];

int cur_edges = 0;
int n;

int get_tree_sz(int from, int to) {
  if (up[to] == from)
    return tree_sz[to];
  return cur_edges - tree_sz[from];
}

bool check_even(int comp_id, int v) {
  return get_tree_sz(comp_id + n, v) % 2 == 0;
}

bool check_triangle(vector<int> vertices) {
  sort(vertices.begin(), vertices.end(), [](int a, int b) {
    return G[a].size() < G[b].size();
  });
  for (int i = 0; i < vertices.size(); ++i)
    id[vertices[i]] = i;
  for (int v : vertices) {
    for (auto [u, i] : G[v]) {
      if (id[u] > id[v]) {
        Gright[v].emplace_back(u, i);
      }
    }
  }
  vector<bool> state(vertices.size(), false);
  for (int v : vertices) {
    for (auto [u, i1] : Gright[v])
      state[id[u]] = true;
    for (auto [u, i1] : Gright[v]) {
      for (auto [x, i2] : Gright[u]) {
        if (state[id[x]]) {
          // triangle!
          // v, u, x
          int comp_id = edge_comp_id[i1];
          bool ok = check_even(comp_id, v) && check_even(comp_id, u) && check_even(comp_id, x);
          
          if (ok)
            return true;
        }
      }
    }
    for (auto [u, i1] : Gright[v])
      state[id[u]] = false;
  }
  return false;
}

pair<int, int> solve(int N, vector<pair<int, int>> edges) {
  ttime = 0;
  n = N;
  int m = edges.size();
  for (int i = 0; i < m; ++i) {
    auto [a, b] = edges[i];
    G[a].emplace_back(b, i);
    G[b].emplace_back(a, i);
  }

  fill(used, used + n, 0);
  int ans_edge = 0;
  int ans_hedg = 0;
  vector<vector<int>> conn_comps;
  for (int i = 0; i < n; ++i) {
    if (used[i])
      continue;
    dfs_dot(i, -1);
    conn_comps.emplace_back(vertices);
    vertices.clear();
  }

  for (int i = 0; i < edge_comps.size(); ++i) {
    //////cerr << "edge_comp " << i << ": ";
    for (int j : edge_comps[i]) {
      //////cerr << j << ' ';
      edge_comp_id[j] = i;
    }
    //////cerr << '\n';
  }
  

  for (int i = 0; i < m; ++i) {
    auto [a, b] = edges[i];
    int j = n + edge_comp_id[i];
    Gtree[j].emplace_back(a);
    Gtree[j].emplace_back(b);
    Gtree[a].emplace_back(j);
    Gtree[b].emplace_back(j);
  }
  for (int i = 0; i < n + edge_comps.size(); ++i) {
    sort(Gtree[i].begin(), Gtree[i].end());
    Gtree[i].resize(unique(Gtree[i].begin(), Gtree[i].end()) - Gtree[i].begin());
  }
  for (int i = 0; i < n + edge_comps.size(); ++i)
    tree_sz[i] = 0;

  for (int i = 0; i < edge_comps.size(); ++i)
    tree_sz[n + i] = edge_comps[i].size();

  vector<int> kek(edge_comps.size());

  for (int j = 0; j < conn_comps.size(); ++j) {
    auto& vertices = conn_comps[j];

    int root = vertices.front();
    dfs_tree(root, -1);

    cur_edges = 0;
    for (int v : vertices)
      cur_edges += G[v].size();
    cur_edges /= 2;
    if (cur_edges % 2 == 0)
      continue;

    // check triangle
    if (check_triangle(vertices)) {
      continue;
    }

    // check hedgehog
    bool can_hedge = false;
    for (int v : vertices) {
      int rem_deg = 0;
      for (int u : Gtree[v]) {
        kek[u - n] = 0;
      }
      for (auto [u, i] : G[v]) {
        int j = edge_comp_id[i];
        ++kek[j];
      }
      for (int u : Gtree[v]) {
        int edges = get_tree_sz(v, u) - kek[u - n];
        rem_deg += kek[u - n] - edges % 2;
      }
      if (rem_deg >= 3)
        can_hedge = true;
    }
    if (can_hedge) {
      ++ans_hedg;
    } else {
      ++ans_edge;
    }
  }

  for (int i = 0; i < n + edge_comps.size(); ++i)
    Gtree[i].clear();
  for (int i = 0; i < n; ++i) {
    Gright[i].clear();
    G[i].clear();
  }
  edge_comps.clear();


  return make_pair(ans_edge, ans_hedg);
}

bool all_comps_even(int n, vector<pair<int, int>> edges) {
  vector<vector<int>> G(n);
  for (auto [a, b] : edges) {
    G[a].emplace_back(b);
    G[b].emplace_back(a);
  }
  vector<bool> used(n, false);
  for (int i = 0; i < n; ++i) {
    if (used[i])
      continue;
    vector<int> cur;
    int q_sz = 0;
    used[i] = true;
    cur.emplace_back(i);
    while (q_sz < cur.size()) {
      int v = cur[q_sz];
      ++q_sz;
      for (int u : G[v]) {
        if (!used[u]) {
          used[u] = true;
          cur.emplace_back(u);
        }
      }
    }
    int total = 0;
    for (int v : cur) {
      //cerr << v << '(' << G[v].size() << ')' << ' ';
      total += G[v].size();
    }
    //cerr << '\n';
    total /= 2;
    //cerr << total << '\n';
    if (total % 2 == 1)
      return false;
  }
  return true;
}

pair<int, int> solve_dumb(int n, vector<pair<int, int>> edges) {
  int m = edges.size();
  vector<vector<int>> G(n);
  vector<vector<bool>> matrix(n, vector<bool>(n, false));
  for (auto [a, b] : edges) {
    G[a].emplace_back(b);
    G[b].emplace_back(a);
    matrix[a][b] = true;
    matrix[b][a] = true;
  }

  auto rem_edge = [](vector<pair<int, int>> edges, pair<int, int> edge) {
    int i = 0;
    pair<int, int> edge_rev(edge.second, edge.first);
    while (edges[i] != edge && edges[i] != edge_rev)
      ++i;
    edges.erase(edges.begin() + i);
    return edges;
  };

  int ans_edge = 0;
  int ans_hedg = 0;
  vector<bool> used(n, false);
  for (int i = 0; i < n; ++i) {
    if (used[i])
      continue;
    vector<int> cur;
    int q_sz = 0;
    cur.emplace_back(i);
    used[i] = true;
    while (q_sz < cur.size()) {
      int v = cur[q_sz];
      ++q_sz;
      for (int u : G[v]) {
        if (!used[u]) {
          used[u] = true;
          cur.emplace_back(u);
        }
      }
    }
    vector<pair<int, int>> cur_edges;
    for (int v : cur) {
      for (int u : G[v]) {
        if (v < u)
          cur_edges.emplace_back(v, u);
      }
    }
    if (cur_edges.size() % 2 == 0)
      continue;
    // 1) check triangle
    bool have = false;
    for (int v : cur) {
      for (int u : G[v]) {
        for (int x : G[u]) {
          if (x == v)
            continue;
          if (!matrix[v][x])
            continue;
          //cerr << v << ' ' << u << ' ' << x << '\n';
          auto kek = rem_edge(rem_edge(rem_edge(cur_edges, make_pair(u, v)), make_pair(v, x)), make_pair(u, x));
          if (all_comps_even(n, kek))
            have = true;
        }
      }
    }
    if (have)
      continue;
    // 2) check hedge
    for (int v : cur) {
      for (int i = 0; i < G[v].size(); ++i) {
        for (int j = i + 1; j < G[v].size(); ++j) {
          for (int k = j + 1; k < G[v].size(); ++k) {
            int a = G[v][i];
            int b = G[v][j];
            int c = G[v][k];
            auto kek = rem_edge(rem_edge(rem_edge(cur_edges, make_pair(v, a)), make_pair(v, b)), make_pair(v, c));
            if (all_comps_even(n, kek))
              have = true;
          }
        }
      }
    }
    if (have) {
      ++ans_hedg;
    } else {
      ++ans_edge;
    }
  }
  return make_pair(ans_edge, ans_hedg);
}

//#define STRESS

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);

#ifdef STRESS
  for (int _ = 0; _ < 100100; ++_) {
    int n = rand() % 5 + 2;
    int m = rand() % (n * (n - 1) / 2) + 1;
    set<pair<int, int>> kek;
    vector<pair<int, int>> edges(m);
    for (int i = 0; i < m; ++i) {
      int a = rand() % (n - 1);
      int b = a + rand() % (n - a - 1) + 1;
      while (kek.count(make_pair(a, b))) {
        a = rand() % (n - 1);
        b = a + rand() % (n - a - 1) + 1;
      }
      kek.emplace(a, b);
      edges[i] = make_pair(a, b);
    }

    auto ans1 = solve(n, edges);
    auto ans2 = solve_dumb(n, edges);
    if (ans1 != ans2) {
      cerr << "BUG!!!\n";
      cerr << m << ' ' << n << '\n';
      for (auto [a, b] : edges)
        cerr << a + 1 << ' ' << b + 1 << '\n';
      cerr << "wrong: ";
      cerr << ans1.first << ' ' << ans1.second << '\n';
      cerr << "right: ";
      cerr << ans2.first << ' ' << ans2.second << "\n\n";
    }
  }

#else  
  int m;
  cin >> m >> n;
  vector<pair<int, int>> edges(m);
  for (int i = 0; i < m; ++i) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    edges[i] = make_pair(a, b);
  }
  auto [ans1, ans2] = solve(n, edges);
  cout << ans1 << ' ' << ans2 << '\n';
#endif
  return 0;
}

詳細信息

Test #1:

score: 100
Accepted
time: 12ms
memory: 17924kb

input:

2 4
1 2
3 4

output:

2 0

result:

ok single line: '2 0'

Test #2:

score: 0
Accepted
time: 7ms
memory: 15932kb

input:

2 3
1 2
3 1

output:

0 0

result:

ok single line: '0 0'

Test #3:

score: 0
Accepted
time: 8ms
memory: 17984kb

input:

5 5
1 2
2 3
2 4
5 2
5 4

output:

0 0

result:

ok single line: '0 0'

Test #4:

score: -100
Wrong Answer
time: 367ms
memory: 201840kb

input:

999990 666660
1 2
1 5
1 7
1 8
1 9
1 10
2 4
2 6
2 9
2 10
3 4
4 8
5 8
6 7
6 10
11 13
11 15
11 20
12 17
12 19
13 16
13 19
14 16
14 19
15 17
15 18
16 17
16 19
17 18
17 20
21 26
21 27
21 29
22 26
22 27
22 29
23 26
23 30
24 26
24 28
25 27
25 30
26 27
26 29
28 29
31 33
31 40
32 35
33 35
33 37
33 38
33 39
3...

output:

383 5252

result:

wrong answer 1st lines differ - expected: '383 523', found: '383 5252'