QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#722532 | #2515. Graph Cards | ucup-team5062# | AC ✓ | 19004ms | 237148kb | C++20 | 6.1kb | 2024-11-07 19:26:21 | 2024-11-07 19:26:22 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
// ================================================================= UF Library
class UnionFind {
public:
vector<int> par;
void init(int sz) {
par.resize(sz, -1);
}
int root(int pos) {
if (par[pos] == -1) return pos;
par[pos] = root(par[pos]);
return par[pos];
}
void unite(int u, int v) {
u = root(u);
v = root(v);
if (u != v) par[u] = v;
}
bool same(int u, int v) {
if (root(u) == root(v)) return true;
return false;
}
};
// ================================================================= Base Function
long long mod1 = 900000011LL;
long long mod2 = 998244353LL;
long long mod3 = 2147483647LL;
long long pow1[1 << 22];
long long pow2[1 << 22];
long long pow3[1 << 22];
long long Rand[1 << 22];
struct Hash {
long long v1, v2, v3;
};
bool isprime(long long x) {
for (long long i = 2; i * i <= x; i++) {
if (x % i == 0) return false;
}
return true;
}
long long get_prime(long long l, long long r) {
while (true) {
long long x = (rand() % 32768) * 32768 + (rand() % 32768);
long long y = x % (r - l + 1) + l;
if (isprime(y) == true) return y;
}
}
bool operator==(const Hash &a1, const Hash &a2) {
if (a1.v1 != a2.v1) return false;
if (a1.v2 != a2.v2) return false;
if (a1.v3 != a2.v3) return false;
return true;
}
bool operator<(const Hash &a1, const Hash &a2) {
if (a1.v1 < a2.v1) return true;
if (a1.v1 > a2.v1) return false;
if (a1.v2 < a2.v2) return true;
if (a1.v2 > a2.v2) return false;
if (a1.v3 < a2.v3) return true;
return false;
}
void Initialize() {
mod1 = get_prime( 900000000LL, 1000000000LL);
mod2 = get_prime(1000000000LL, 1100000000LL);
mod3 = get_prime(1100000000LL, 1200000000LL);
pow1[0] = 1; for (int i = 1; i <= 2000000; i++) pow1[i] = (222222223LL * pow1[i - 1]) % mod1;
pow2[0] = 1; for (int i = 1; i <= 2000000; i++) pow2[i] = (222222223LL * pow2[i - 1]) % mod2;
pow3[0] = 1; for (int i = 1; i <= 2000000; i++) pow3[i] = (222222223LL * pow3[i - 1]) % mod3;
map<long long, long long> Map;
long long x = 869120;
for (int i = 0; i <= 2000000; i++) {
while (true) {
long long r = (rand() % 32768) * 32768 + (rand() % 32768);
long long v = (r + x) % mod1;
if (Map[v] == 0) {
Rand[i] = v;
Map[v] = 1;
x = (x * 3LL) % mod1;
break;
}
}
}
}
Hash Apply(Hash a1, Hash a2) {
Hash a3;
a3.v1 = (222222223LL * a1.v1 + a2.v1) % mod1;
a3.v2 = (222222223LL * a1.v2 + a2.v2) % mod2;
a3.v3 = (222222223LL * a1.v3 + a2.v3) % mod3;
return a3;
}
Hash CycleHash(vector<Hash> vec) {
Hash minv = {mod1 - 1, mod2 - 1, mod3 - 1};
int N = vec.size();
// Get Hash
for (int t = 0; t < 2; t++) {
vector<Hash> cur(2 * N + 1);
cur[0] = Hash{0LL, 0LL, 0LL};
for (int i = 0; i < 2 * N; i++) cur[i + 1] = Apply(cur[i], vec[i % N]);
for (int i = 0; i < N; i++) {
Hash p;
p.v1 = (cur[N + i].v1 - cur[i].v1 * pow1[N] + mod1 * mod1) % mod1;
p.v2 = (cur[N + i].v2 - cur[i].v2 * pow2[N] + mod2 * mod2) % mod2;
p.v3 = (cur[N + i].v3 - cur[i].v3 * pow3[N] + mod3 * mod3) % mod3;
minv = min(minv, p);
}
reverse(vec.begin(), vec.end());
}
return minv;
}
Hash GraphHash(int pos, int pre, vector<vector<int>> &G) {
vector<Hash> V;
for (int to : G[pos]) {
if (to == pre) continue;
Hash ret = GraphHash(to, pos, G);
V.push_back(ret);
}
sort(V.begin(), V.end());
Hash p = {2024LL, 2024LL, 2024LL};
for (int i = 0; i < (int)V.size(); i++) p.v1 = (277277277LL * (p.v1 * p.v1 % mod1) + V[i].v1 * Rand[i]) % mod1;
for (int i = 0; i < (int)V.size(); i++) p.v2 = (277277277LL * (p.v2 * p.v2 % mod2) + V[i].v2 * Rand[i]) % mod2;
for (int i = 0; i < (int)V.size(); i++) p.v3 = (277277277LL * (p.v3 * p.v3 % mod3) + V[i].v3 * Rand[i]) % mod3;
return p;
}
// ================================================================= Others
void dfs(int pos, int goal, int pre, vector<int> &Current, vector<int> &Answer, vector<vector<int>> &G) {
if (pos == goal) {
Answer = Current;
return;
}
for (int to : G[pos]) {
if (to == pre) continue;
Current.push_back(to);
dfs(to, goal, pos, Current, Answer, G);
Current.pop_back();
}
}
pair<int, Hash> GetTotalHash(int N, vector<pair<int, int>> Edges) {
UnionFind UF; UF.init(N + 1);
vector<vector<int>> G(N, vector<int>(0, 0));
vector<vector<int>> H(N, vector<int>(0, 0));
vector<int> Path;
vector<bool> IsCycle(N, false);
// Get Cycle
for (int i = 0; i < (int)Edges.size(); i++) {
if (UF.same(Edges[i].first, Edges[i].second) == true) {
vector<int> tmp = {Edges[i].first};
dfs(Edges[i].first, Edges[i].second, -1, tmp, Path, G);
}
else {
UF.unite(Edges[i].first, Edges[i].second);
G[Edges[i].first].push_back(Edges[i].second);
G[Edges[i].second].push_back(Edges[i].first);
}
}
// Get New Graph
for (int idx : Path) IsCycle[idx] = true;
for (pair<int, int> e : Edges) {
if (IsCycle[e.first] == true && IsCycle[e.second] == true) continue;
H[e.first].push_back(e.second);
H[e.second].push_back(e.first);
}
// Get Hash
vector<Hash> E(Path.size());
for (int i = 0; i < (int)Path.size(); i++) {
E[i] = GraphHash(Path[i], -1, H);
}
return make_pair(Path.size(), CycleHash(E));
}
int main() {
int T; scanf("%d", &T);
Initialize();
for (int t = 1; t <= T; t++) {
int N; scanf("%d", &N);
vector<vector<pair<int, int>>> Graph(N);
// Input Graph
for (int i = 0; i < N; i++) {
int K; scanf("%d", &K);
Graph[i].resize(K, make_pair(0, 0));
for (int j = 0; j < K; j++) {
scanf("%d%d", &Graph[i][j].first, &Graph[i][j].second);
Graph[i][j].first -= 1;
Graph[i][j].second -= 1;
}
}
// Get Hash
vector<tuple<int, int, Hash>> Answer(N);
for (int i = 0; i < N; i++) {
pair<int, Hash> v = GetTotalHash(Graph[i].size(), Graph[i]);
Answer[i] = make_tuple(Graph[i].size(), v.first, v.second);
}
sort(Answer.begin(), Answer.end());
Answer.erase(unique(Answer.begin(), Answer.end()), Answer.end());
// Output
printf("%d\n", (int)Answer.size());
}
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 1902ms
memory: 201412kb
input:
1 2 4 1 2 2 3 3 1 1 4 4 1 2 2 3 3 1 2 4
output:
1
result:
ok single line: '1'
Test #2:
score: 0
Accepted
time: 1888ms
memory: 193592kb
input:
2 2 4 1 2 2 3 3 1 1 4 5 1 2 2 3 3 1 2 4 2 5 3 9 1 2 2 5 5 7 7 6 6 3 3 1 2 4 7 9 9 8 9 1 4 4 2 2 3 3 5 5 7 7 6 6 4 7 8 8 9 9 1 2 2 5 5 4 4 1 4 7 7 8 8 6 8 9 5 3
output:
2 2
result:
ok 2 lines
Test #3:
score: 0
Accepted
time: 11352ms
memory: 201092kb
input:
30 332526 3 3 2 3 1 2 1 3 2 3 3 1 1 2 3 1 3 1 2 3 2 3 3 2 2 1 1 3 3 2 1 2 3 1 3 3 1 3 1 2 3 2 3 1 2 2 3 3 1 3 2 1 2 3 1 3 3 3 1 3 2 1 2 3 1 3 1 2 3 2 3 1 3 3 2 2 1 3 1 2 2 3 3 1 3 3 1 3 2 1 2 3 2 1 2 3 1 3 3 3 2 2 1 1 3 3 1 2 1 3 2 3 3 1 2 1 3 2 3 3 2 3 2 1 3 1 3 1 2 1 3 2 3 3 3 1 1 2 2 3 3 1 3 1 2 ...
output:
1 4 5 89 93 242 628 1575 3401 5703 7718 8888 9258 9355 9356 9203 9211 89 239 648 1739 4541 10352 19037 27089 31567 33030 33068 32480 31503
result:
ok 30 lines
Test #4:
score: 0
Accepted
time: 9993ms
memory: 200012kb
input:
30 333333 3 2 1 2 3 3 1 3 1 2 3 2 3 1 3 3 2 1 3 1 2 3 2 3 2 1 3 1 3 2 3 2 1 1 3 3 1 2 3 2 3 1 3 3 1 2 1 3 2 3 1 3 1 2 3 2 3 1 3 2 3 1 2 3 2 1 3 2 3 1 3 2 3 1 2 1 3 3 3 1 1 2 3 2 3 3 2 3 1 1 2 3 2 1 3 1 3 2 3 3 2 1 2 3 1 3 3 2 1 2 1 3 3 2 3 2 1 1 3 3 1 2 3 2 3 1 3 3 1 1 2 3 2 3 1 3 1 2 2 3 3 1 2 3 2 ...
output:
1 2 5 13 33 89 240 653 1771 4753 11868 24982 40524 51128 54690 54119 52143 49848 47551 45441 43471 41664 40000 38461 37037 35714 34482 33333 32258 31250
result:
ok 30 lines
Test #5:
score: 0
Accepted
time: 19004ms
memory: 237148kb
input:
30 2 500000 12446 494050 179161 216388 282442 232792 428247 130742 87062 493860 276791 469755 342468 58973 93535 429405 5662 112197 121541 62083 28611 427877 376918 349780 372239 58010 457751 308686 448844 473714 151350 480692 152372 415617 311966 298916 302690 200753 75481 396263 318635 79619 39930...
output:
1 2 2 1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2 1 1 2
result:
ok 30 lines
Test #6:
score: 0
Accepted
time: 2149ms
memory: 217972kb
input:
1 4 240000 1 2 2 3 3 4 4 7 1 5 2 6 7 8 8 9 9 10 10 13 7 11 8 12 13 14 14 15 15 16 16 19 13 17 14 18 19 20 20 21 21 22 22 25 19 23 20 24 25 26 26 27 27 28 28 31 25 29 26 30 31 32 32 33 33 34 34 37 31 35 32 36 37 38 38 39 39 40 40 43 37 41 38 42 43 44 44 45 45 46 46 49 43 47 44 48 49 50 50 51 51 52 52...
output:
2
result:
ok single line: '2'