抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

构造一个 n3n^3 个点的无向图 GG,方法如下:

  1. 给定 33nn 个点的无向图 G1,G2,G3G_1,G_2,G_3
  2. 构造 n3n^3 个点,标号是一个三元组 <i,j,k>\left<i,j,k\right>
  3. 对于 G1G_1 中的边 <u,v>\left<u,v\right>,连边 <u,j,k>\left<u,j,k\right><v,j,k>\left<v,j,k\right>
  4. 对于 G2G_2 中的边 <u,v>\left<u,v\right>,连边 <i,u,k>\left<i,u,k\right><i,v,k>\left<i,v,k\right>
  5. 对于 G3G_3 中的边 <u,v>\left<u,v\right>,连边 <i,j,u>\left<i,j,u\right><i,j,v>\left<i,j,v\right>
  6. 对于 GG 上的一个点 <i,j,k>\left<i,j,k\right>,其点权为 1018(i+j+k){10}^{18(i+j+k)}

现在,要你求出 GG 的最大独立集大小膜 998244353998244353 以后的值。

2n105,1m1,m2,m31052\le n\le 10^5,1\le m_1,m_2,m_3\le 10^5

考虑到是点权是一个大数的幂次,那肯定是选的数越大越好。

考虑如果你知道了图 GG 之后你会怎么做。

首先 <n,n,n>\left<n,n,n\right> 这个点必须得选,然后其跟她连边的点就不能选了。

然后如果一个点已经确定了旁边已经比她大的点都不选了,那么她才会选。

那会不会有两个相邻的点点权相等呢?显然不会。因为相邻的点必须有两个权值相等,那么另外一个肯定相等,这是不合法的。

然后我们就考虑这个过程,就是我们考虑如何判断一个点选不选,那就要看与之相邻的比她大的点选不选,就是如果那些点都是不合法的,那么这个点合法,否则不合法。

我们发现这跟博弈问题很像,就是有 33 颗棋子,每个人每次可以把一个棋子移动到一个比她大的格子里,不能走的就输了。而先手必输态的点就是合法的。

于是我们只要计算每个点的 sg 值即可。

考虑到每张图 sg 值只会有 O(n)\mathcal{O}(\sqrt n) 个,我们只要计算出之后暴力合并即可,于是合并复杂度是 O(n)\mathcal{O}(n) 的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
namespace dfcmd {

typedef long long LL;

const int maxn = 100005;
const int mod = 998244353;
const int di = 1000000000000000000LL % mod;

int bin[maxn];

inline void add(int& x, int y) {
x += y;
if (x >= mod) {
x -= mod;
}
}

int n;

struct myhnb {
int m;
int sg[maxn];
int ss[maxn];

struct Edge {
int to, nxt;
} e[maxn];

int first[maxn];
int cnt = 0;

inline void add_edge(int u, int v) {
if (u > v) {
swap(u, v);
}
e[++cnt].nxt = first[u];
first[u] = cnt;
e[cnt].to = v;
}

int vis[maxn];

myhnb() {
memset(first, 0, sizeof(first));
memset(ss, 0, sizeof(ss));
memset(vis, 0, sizeof(vis));
}

inline void Dfs() {
for (int now = n; now; --now) {
vis[now] = true;
set<int> sgg;
sgg.clear();
for (int i = first[now]; i; i = e[i].nxt) {
sgg.insert(sg[e[i].to]);
}
sg[now] = 0;
while (sgg.count(sg[now])) {
sg[now]++;
}
add(ss[sg[now]], bin[now]);
}
}

inline int& operator [] (int x) {
return ss[x];
}
} d[3];

int main() {
read(n);
bin[0] = 1;
for (int i = 1; i <= n; ++i) {
bin[i] = (LL) bin[i - 1] * di % mod;
}
for (int i = 0; i < 3; ++i) {
read(d[i].m);
for (int j = 1; j <= d[i].m; ++j) {
int u, v;
read(u), read(v);
d[i].add_edge(u, v);
}
d[i].Dfs();
}
int ans = 0;
for (int i = 0; i <= 1000; ++i) {
for (int j = 0; j <= 1000; ++j) {
add(ans, (LL) d[0][i] * d[1][j] % mod * d[2][i ^ j] % mod);
}
}
writeln(ans);
return 0;
}
}

评论