QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#315115#2210. Hamilton PathelimvaRE 0ms0kbC++206.8kb2024-01-26 23:48:382024-01-26 23:48:39

Judging History

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

  • [2024-01-26 23:48:39]
  • 评测
  • 测评结果:RE
  • 用时:0ms
  • 内存:0kb
  • [2024-01-26 23:48:38]
  • 提交

answer

#include <bits/stdc++.h>

using int64 = long long;

const int N = 5e5 + 10;
const int mod = 1e9 + 7;

std::vector<int> edges[N], pred[N];
std::map<int, int> from[N];
int dsu[N], head[N], tail[N], next[N];
int deg[N], prev[N];
;
int64 pw[N];
int n, m;

int get(int x) {
  if (dsu[x] != x) dsu[x] = get(dsu[x]);
  return dsu[x];
}

bool check(const std::vector<int> &path) {
  std::vector<int> idx(n);
  for (int i = 0; i < n; ++i) idx.at(path[i]) = i;
  for (int u = 0; u < n; ++u) {
    for (auto &v : edges[u]) {
      int i = idx[u], j = idx[v];
      if (i < j && i + 1 != j) return false;
    }
  }
  return true;
};

int process(const std::vector<int> &forbid, std::vector<std::pair<int, int>> &extra) {
  for (int i = 0; i < n; ++i) {
    head[i] = tail[i] = dsu[i] = i;
    prev[i] = next[i] = -1;
    deg[i] = 0;
    from[i].clear();
  }
  int cnt = 0;
  for (int i = 0; i < n; ++i) if (!forbid[i]) {
    ++cnt;
    for (auto &v : edges[i]) if (!forbid[v]) {
      deg[i]++; from[v][i]++;
    }
  }
  std::vector<int> queue;
  for (int i = 0; i < n; ++i) {
    if (deg[i] == 1 && !forbid[i]) queue.push_back(i);
  }
  for (size_t i = 0; i < queue.size(); ++i) {
    int ru = get(queue[i]);
    int u = tail[get(queue[i])];
    if (deg[u] != 1) continue;
    int go = -1;
    for (auto &v : edges[u]) if (!forbid[v]) {
      if (get(v) != ru) go = v;
    }
    assert(go != -1);
    int rg = get(go), v = tail[rg];
    if (head[rg] == go) {
      next[u] = go; prev[go] = u;
      dsu[rg] = ru; tail[ru] = v;
      if (from[ru].size() < from[rg].size()) {
        std::swap(from[ru], from[rg]);
      }
      cnt -= 1;
      for (auto &e : from[rg]) from[ru][e.first] += e.second;
      auto it = from[ru].find(v);
      if (it != from[ru].end()) {
        deg[v] -= it->second;
        from[ru].erase(it);
        if (deg[v] == 1) queue.push_back(v);
      }
    } else {
      extra.emplace_back(u, go);
    }
  }
  return cnt;
}

int main() {
  int T, type;
  scanf("%d%d", &type, &T);
  for (int cas = 1; cas <= T; ++cas) {
    scanf("%d%d", &n, &m);
    pw[0] = 1;
    for (int i = 1; i <= n; ++i) {
      pw[i] = pw[i - 1] * 10 % mod;
    }
    for (int i = 0; i < n; ++i) {
      pred[i].clear();
      edges[i].clear();
    }
    for (int i = 0; i < m; ++i) {
      int u, v;
      scanf("%d%d", &u, &v);
      edges[u - 1].push_back(v - 1);
      if (cas == 11660)
        fprintf(stderr, "%d %d\n", u, v);
    }
    for (int i = 0; i < n; ++i) {
      std::sort(edges[i].begin(), edges[i].end());
      edges[i].erase(std::unique(edges[i].begin(), edges[i].end()), edges[i].end());
    }
    std::vector<int> forbid(n);
    for (int i = 0; i < n; ++i) pred[i].clear();
    for (int i = 0; i < n; ++i) {
      for (auto &v : edges[i]) pred[v].push_back(i);
    }

    std::vector<std::pair<int, int>> extra;
    int cnt = process(forbid, extra);

    auto get_sum = [&](const std::vector<int> &path) {
      int64 sum = 0;
      for (int i = 0; i < n; ++i) {
        sum = (sum + (path[i] + 1) * pw[n - 1 - i]) % mod;
      }
      return sum;
    };

    std::vector<std::pair<int, int64>> ret;

    auto brute = [&](int s) {
      std::vector<int> path = {s};
      std::vector<bool> mark(n);
      mark[s] = true;
      for (int i = 1; i < n; ++i) {
        int go = -1, cnt = 0;
        for (auto &x : pred[s]) if (!mark[x]) {
          go = x;
          cnt++;
        }
        if (cnt != 1) break;
        path.push_back(s = go);
        mark[s] = true;
      }
      if (path.size() != n) return;
      std::reverse(path.begin(), path.end());
      if (check(path)) ret.emplace_back(path[0], get_sum(path));
    };

    if (cnt == 1) {
      int u = head[get(0)], v = tail[get(0)];
      std::vector<int> path, idx(n);
      for (int x = u; x != -1; x = next[x]) {
        idx[x] = path.size();
        path.push_back(x);
      }
      int64 sum = get_sum(path);
      std::vector<int> mark(n + 1);
      std::vector<bool> visited(n);
      for (int i = 0; i + 1 < n; ++i) {
        for (auto &v : edges[path[i]]) if (v != path[i + 1]) {
          mark[idx[v] + 1]++;
          mark[i + 1]--;
        }
      }
      for (int i = 1; i <= n; ++i) mark[i] += mark[i - 1];
      int best = -1;
      for (auto &x : edges[v]) {
        visited[idx[x]] = true;
        if (idx[x] != 0 && (best == -1 || best > idx[x]))
          best = idx[x];
      }
      if (best != -1) {
        for (int i = best + 1; i < n; ++i) mark[i]++;
      }
      if (visited[0]) {
        for (int i = 0; i < n; ++i) {
          if (!mark[i]) ret.emplace_back(path[i], sum);
          sum = sum - (path[i] + 1) * pw[n - 1] % mod;
          sum = (sum + mod) % mod;
          sum = (sum * 10 + path[i] + 1) % mod;
        }
      } else {
        ret = {{path[0], sum}};
        int middle = -1;
        for (int i = 0; i < n; ++i) {
          bool found = false;
          for (auto &x : edges[path[i]]) {
            if (idx[x] == 0) found = true;
          }
          if (found) middle = i;
        }
        if (middle != -1) {
          int end = -1;
          for (int i = 1; i <= middle; ++i) {
            for (auto &x: pred[path[i]]) if (idx[x] > middle) {
              end = i;
            }
          }
          if (end != -1) brute(path[end - 1]);
        }
      }
    } else {
      std::vector<std::pair<int, int>> bad;
      for (auto &e : extra) {
        int u = get(e.first), v = get(e.second);
        if (u != v && tail[u] == e.first) bad.push_back(e);
      }
      if (bad.size() >= 1) {
        for (size_t i = 0; i < bad.size() && i < 2; ++i) {
          int u = bad[i].first, v = bad[i].second;
          brute(u);
          std::vector<int> path, idx(n, -1), bad(n + 1);
          for (u = head[get(v)]; u != v; u = next[u]) path.push_back(u);
          for (size_t i = 0; i < path.size(); ++i) idx[path[i]] = i;
          for (size_t i = 1; i < path.size(); ++i) {
            for (auto &x: edges[path[i]]) if (idx[x] != -1 && idx[x] < i) {
              if (idx[x] != 0) bad[idx[x]]++, bad[i]--;
            }
          }
          for (int i = 1; i <= n; ++i) bad[i] += bad[i - 1];
          int end = path[0];
          for (size_t i = 1; i < path.size(); ++i) {
            int found = 0;
            for (auto &x: pred[path[i]]) found |= idx[x] == -1;
            if (found) break;
            if (!bad[i]) end = path[i];
          }
          brute(end);
        }
      }
    }
    std::sort(ret.begin(), ret.end());
    ret.erase(std::unique(ret.begin(), ret.end()), ret.end());
    printf("%d\n", (int)ret.size());
    for (size_t i = 0; i < ret.size(); ++i) {
      printf("%lld", ret[i].second);
      putchar(" \n"[i + 1 == ret.size()]);
    }
  }
  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Runtime Error

input:

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

output:


result: