QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#334031 | #2210. Hamilton Path | hos_lyric | ML | 0ms | 3796kb | C++14 | 10.3kb | 2024-02-21 01:11:13 | 2024-02-21 01:11:13 |
Judging History
answer
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")
////////////////////////////////////////////////////////////////////////////////
template <unsigned M_> struct ModInt {
static constexpr unsigned M = M_;
unsigned x;
constexpr ModInt() : x(0U) {}
constexpr ModInt(unsigned x_) : x(x_ % M) {}
constexpr ModInt(unsigned long long x_) : x(x_ % M) {}
constexpr ModInt(int x_) : x(((x_ %= static_cast<int>(M)) < 0) ? (x_ + static_cast<int>(M)) : x_) {}
constexpr ModInt(long long x_) : x(((x_ %= static_cast<long long>(M)) < 0) ? (x_ + static_cast<long long>(M)) : x_) {}
ModInt &operator+=(const ModInt &a) { x = ((x += a.x) >= M) ? (x - M) : x; return *this; }
ModInt &operator-=(const ModInt &a) { x = ((x -= a.x) >= M) ? (x + M) : x; return *this; }
ModInt &operator*=(const ModInt &a) { x = (static_cast<unsigned long long>(x) * a.x) % M; return *this; }
ModInt &operator/=(const ModInt &a) { return (*this *= a.inv()); }
ModInt pow(long long e) const {
if (e < 0) return inv().pow(-e);
ModInt a = *this, b = 1U; for (; e; e >>= 1) { if (e & 1) b *= a; a *= a; } return b;
}
ModInt inv() const {
unsigned a = M, b = x; int y = 0, z = 1;
for (; b; ) { const unsigned q = a / b; const unsigned c = a - q * b; a = b; b = c; const int w = y - static_cast<int>(q) * z; y = z; z = w; }
assert(a == 1U); return ModInt(y);
}
ModInt operator+() const { return *this; }
ModInt operator-() const { ModInt a; a.x = x ? (M - x) : 0U; return a; }
ModInt operator+(const ModInt &a) const { return (ModInt(*this) += a); }
ModInt operator-(const ModInt &a) const { return (ModInt(*this) -= a); }
ModInt operator*(const ModInt &a) const { return (ModInt(*this) *= a); }
ModInt operator/(const ModInt &a) const { return (ModInt(*this) /= a); }
template <class T> friend ModInt operator+(T a, const ModInt &b) { return (ModInt(a) += b); }
template <class T> friend ModInt operator-(T a, const ModInt &b) { return (ModInt(a) -= b); }
template <class T> friend ModInt operator*(T a, const ModInt &b) { return (ModInt(a) *= b); }
template <class T> friend ModInt operator/(T a, const ModInt &b) { return (ModInt(a) /= b); }
explicit operator bool() const { return x; }
bool operator==(const ModInt &a) const { return (x == a.x); }
bool operator!=(const ModInt &a) const { return (x != a.x); }
bool operator<(const ModInt &a) const { return (x < a.x); }
friend std::ostream &operator<<(std::ostream &os, const ModInt &a) { return os << a.x; }
};
////////////////////////////////////////////////////////////////////////////////
constexpr unsigned MO = 1000000007;
using Mint = ModInt<MO>;
int root(vector<int> &uf, int u) {
return (uf[u] < 0) ? u : (uf[u] = root(uf, uf[u]));
}
bool connect(vector<int> &uf, int u, int v) {
u = root(uf, u);
v = root(uf, v);
if (u == v) return false;
if (uf[u] > uf[v]) swap(u, v);
uf[u] += uf[v];
uf[v] = u;
return true;
}
int N, M;
vector<pair<int, int>> E;
bool adj(int u, int v) {
auto it = lower_bound(E.begin(), E.end(), make_pair(u, v));
return (it != E.end() && *it == make_pair(u, v));
}
vector<vector<int>> graph, hparg;
vector<pair<int, Mint>> ans;
void go(int src) {
int len = 0;
Mint key = 0;
vector<int> vis(N, 0);
for (int u = src; ; ) {
(key *= 10) += (u + 1);
vis[u] = 1;
if (++len == N) {
ans.emplace_back(src, key);
return;
}
int vm = -1;
for (const int v : graph[u]) if (!vis[v]) {
if (~vm) return;
vm = v;
}
if (!~vm) return;
u = vm;
}
}
void og(int snk) {
int len = 0;
Mint key = 0, ten = 1;
vector<int> vis(N, 0);
for (int u = snk; ; ) {
key += (u + 1) * ten;
ten *= 10;
vis[u] = 1;
if (++len == N) {
// OK
ans.emplace_back(u, key);
return;
}
int vm = -1;
for (const int v : hparg[u]) if (!vis[v]) {
if (~vm) return;
vm = v;
}
if (!~vm) return;
u = vm;
}
}
int main() {
for (int numCases; ~scanf("%d", &numCases); ) { for (int caseId = 1; caseId <= numCases; ++caseId) {
scanf("%d%d", &N, &M);
E.resize(M);
for (int i = 0; i < M; ++i) {
scanf("%d%d", &E[i].first, &E[i].second);
--E[i].first;
--E[i].second;
}
sort(E.begin(), E.end());
E.erase(unique(E.begin(), E.end()), E.end());
M = E.size();
graph.assign(N, {});
hparg.assign(N, {});
for (int i = 0; i < M; ++i) {
const int u = E[i].first, v = E[i].second;
graph[u].push_back(v);
hparg[v].push_back(u);
}
ans.clear();
// for (int u = 0; u < N; ++u) go(u);
// for (int u = 0; u < N; ++u) og(u);
vector<int> indeg(N, 0), outdeg(N, 0);
for (int i = 0; i < M; ++i) {
const int u = E[i].first, v = E[i].second;
++outdeg[u];
++indeg[v];
}
// component: l -> * -> ... * -> r determined
vector<int> uf(N, -1);
vector<int> ls(N), rs(N);
vector<int> nxt(N, -1), prv(N, -1);
for (int u = 0; u < N; ++u) ls[u] = rs[u] = u;
auto L = [&](int u) -> int & { return ls[root(uf, u)]; };
auto R = [&](int u) -> int & { return rs[root(uf, u)]; };
auto isGood = [&](int u, int v) -> bool {
return (root(uf, u) != root(uf, v) && R(u) == u && L(v) == v);
};
queue<int> que;
auto check = [&](int u) -> void {
if (indeg[L(u)] >= 2 && outdeg[R(u)] == 1) que.push(R(u));
if (indeg[L(u)] == 1 && outdeg[R(u)] >= 1) que.push(L(u));
};
for (int u = 0; u < N; ++u) {
if (indeg[u] == 0) { go(u); goto done; }
if (outdeg[u] == 0) { og(u); goto done; }
check(u);
}
for (; que.size(); ) {
const int u = que.front();
que.pop();
if (indeg[L(u)] >= 2 && outdeg[R(u)] == 1 && R(u) == u) {
for (const int v : graph[u]) if (isGood(u, v)) {
// cerr<<__LINE__<<"> u="<<u<<" -> v="<<v<<endl;
for (const int w : hparg[v]) if (u != w && isGood(w, v)) {
--outdeg[w];
check(w);
}
const int l = L(u), r = R(v);
connect(uf, u, v);
L(u) = l; R(u) = r;
nxt[u] = v; prv[v] = u;
break;
}
assert(R(u) != u);
} else if (indeg[L(u)] == 1 && outdeg[R(u)] >= 2 && L(u) == u) {
for (const int v : hparg[u]) if (isGood(v, u)) {
// cerr<<__LINE__<<"> v="<<v<<" -> u="<<u<<endl;
for (const int w : graph[v]) if (u != w && isGood(v, w)) {
--outdeg[w];
check(w);
}
const int l = L(v), r = R(u);
connect(uf, v, u);
L(u) = l; R(u) = r;
nxt[v] = u; prv[u] = v;
break;
}
assert(L(u) != u);
} else {
continue;
}
// useless edge
if (adj(R(u), L(u))) {
--outdeg[R(u)];
--indeg[L(u)];
}
check(u);
}
for (int u = 0; u < N; ++u) if (R(u) == u) {
// (>= 2 such components ==> impossible)
if (indeg[L(u)] >= 2 && outdeg[R(u)] >= 2) {
int cnt = 0;
// >= 3 such v ==> impossible
for (const int v : graph[u]) if (isGood(u, v)) {
// cerr<<__LINE__<<"> "<<u<<" "<<v<<endl;
go(v);
if (++cnt == 2) break;
}
goto done;
}
}
// a Hamiltonian cycle left
{
// cerr<<__LINE__<<"> nxt = "<<nxt<<", prv = "<<prv<<endl;
for (int i = 0; i < M; ++i) {
const int u = E[i].first, v = E[i].second;
if (isGood(u, v)) {
nxt[u] = v;
prv[v] = u;
}
}
vector<int> us;
for (int u = 0; ; ) {
us.push_back(u);
if ((u = nxt[u]) == 0) break;
}
// cerr<<__LINE__<<"> us = "<<us<<endl;
assert((int)us.size() == N);
vector<int> su(N, -1);
for (int j = 0; j < N; ++j) su[us[j]] = j;
vector<int> fs(N + 1, 0);
for (int i = 0; i < M; ++i) {
const int u = E[i].first, v = E[i].second;
if ((su[u] + 1) % N != su[v]) {
// bad: (su[v], su[u]]
if (su[v] < su[u]) {
++fs[su[v] + 1];
--fs[su[u] + 1];
} else {
++fs[su[v] + 1];
--fs[N];
++fs[0];
--fs[su[u] + 1];
}
}
}
for (int j = 0; j < N; ++j) fs[j + 1] += fs[j];
// cerr<<__LINE__<<"> fs = "<<fs<<endl;
const Mint ten = Mint(10).pow(N - 1);
Mint key = 0;
for (int j = 0; j < N; ++j) (key *= 10) += (us[j] + 1);
for (int j = 0; j < N; ++j) {
if (!fs[j]) {
ans.emplace_back(us[j], key);
}
key -= (us[j] + 1) * ten;
key *= 10;
key += (us[j] + 1);
}
}
done:{}
#ifdef LOCAL
cerr<<"ans = "<<ans<<endl;
#endif
sort(ans.begin(), ans.end());
printf("%d\n", (int)ans.size());
if (ans.size()) {
for (int i = 0; i < (int)ans.size(); ++i) {
if (i) printf(" ");
printf("%u", ans[i].second.x);
}
puts("");
}
}
#ifndef LOCAL
break;
#endif
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3796kb
input:
1 5 6 3 4 2 5 5 3 1 3 4 2 5 1
output:
2 13425 34251
result:
ok 3 number(s): "2 13425 34251"
Test #2:
score: -100
Memory Limit Exceeded
input:
67777 9 32 6 3 5 2 7 3 7 8 5 2 5 2 7 8 8 2 7 3 8 9 4 3 2 3 4 3 3 1 1 3 8 3 9 8 3 2 5 6 4 5 9 4 6 7 2 8 5 4 5 3 7 8 5 1 6 9 8 3 6 9 7 8 4 1 5 12 3 5 2 3 4 5 2 5 5 3 1 4 3 2 2 4 1 4 4 1 2 5 4 5 2 10 1 2 1 2 1 2 2 1 1 2 1 2 1 2 1 2 1 2 1 2 10 28 1 9 5 9 6 1 10 5 8 7 1 4 7 10 7 5 6 8 9 4 2 9 6 4 2 6 1 1...