题目描述

给定一张 $n$ 个顶点 $m$ 条边的连通无向简单图 $G$,保证 $G$ 至少存在一个圈。求所有的正整数 $k$,使得 $G$ 的所有边可以被 $k-$染色,满足对于 $G$ 中任意一个 (简单) 圈,每种颜色的边的数量都相同

输入格式

第一行包含两个正整数 $n, m$ ($n, m \leq 2000$),分别表示 $G$ 的点数和边数。

接下来 $m$ 行,每行两个正整数 $a_i, b_i$ ($1 \leq a_i, b_i \leq n$),表示 $G$ 中有一条连接顶点 $a_i, b_i$ 的无向边,保证图中没有重边。

输出格式

输出一行,包含若干个整数,以递增的顺序输出所有可行的正整数 $k$。由于 $G$ 中存在至少一个圈,因此这样的 $k$ 是有限的。

题解

首先,若 $e$ 是 $G$ 的割边,则 $e$ 不在 $G$ 的任何一个圈上,因此它的颜色对整张图毫无影响,因此我们先将 $G$ 的割边去掉。

下面先假设 $G$ 连通,即 $G$ 是 $2-$边连通图的情形。

在这里,我们要引入一个 (连通性) 图论中非常重要的概念:切边等价 (Cut edge equivalent)。下面给出定义:

(定义 1) 对于 $2-$边连通图 $G$,定义边 $e_1, e_2$ 切边等价,当且仅当在 $G$ 的所有 (简单) 圈中,$e_1$ 和 $e_2$ 要么同时出现,要么同时不出现

也就是说,$e_1$ 和 $e_2$ 切边等价 $\Leftrightarrow \left( \forall \text{cycle } C, e_1 \in C \Leftrightarrow e_2 \in C \right)$。从中立即可以看出

(性质 1) "切边等价" 是等价关系。即 "切边等价" 具有自反性、对称性和传递性

(ps: 以下我们在讨论切边等价时,默认 $e_1 \neq e_2$)

(定义 2) 定义 $\left( e_1, e_2 \right)$ 是切边对 (Cut pair),如果 $G \setminus \left\{ e_1, e_2 \right\}$ 不连通

切边等价和切边对有着如下关系:

(定理 1) 对于 $2-$边连通图 $G$,$e_1, e_2$ 切边等价,当且仅当 $\left( e_1, e_2 \right)$ 是切边对

证明

若 $e_1, e_2$ 切边等价,则删去 $e_1$ 后,$e_2$ 不能在任何一个圈上。

否则,$e_2$ 所在的圈上没有 $e_1$,与定义矛盾。

于是 $e_2$ 是 $G \setminus \left\{ e_1 \right\}$ 的桥边,从而 $\left( e_1, e_2 \right)$ 是切边对。

反之,若 $\left( e_1, e_2 \right)$ 是切边对,则 $e_2$ 是 $G \setminus \left\{ e_1 \right\}$ 的桥边。

于是不存在只过 $e_2$ 不过 $e_1$ 的圈。同理不存在只过 $e_1$ 不过 $e_2$ 的圈,从而 $e_1, e_2$ 切边等价。

回忆我们在 [lydsy3569]DZY Loves Chinese Ⅱ 中定义的边 $e$ 的权值 $C \left( e \right)$,我们有如下结论:

(定理 2) 对于 $2-$边连通图 $G$,$e_1, e_2$ 切边等价,当且仅当 $C \left( e_1 \right) = C \left( e_2 \right)$

证明

由定理 1 知,$e_1, e_2$ 切边等价 $\Leftrightarrow G \setminus \left\{ e_1, e_2 \right\}$ 不连通。

由那道题的主定理知,这当且仅当 $C \left( e_1 \right), C \left( e_2 \right)$ 线性相关。

而在 $2-$边连通图中,由于没有桥边,因此 $C \left( e \right) \neq \varnothing$。因此 $C \left( e_1 \right), C \left( e_2 \right)$ 线性相关当且仅当 $C \left( e_1 \right) = C \left( e_2 \right)$。


回到原题。由于 "切边等价" 是一个等价关系,因此可以把一张 $2-$边连通图根据 "切边等价" 的关系划分为若干个等价类 $E_1, E_2, \cdots, E_\kappa$。

考虑每个等价类,如果每个等价类的大小都是 $k$ 的倍数 (即 $k \mid \gcd \left( \left| E_1 \right|, \left| E_2 \right|, \cdots, \left| E_\kappa \right| \right)$),那么它显然可以是实现的 (注意到把每个等价类均匀 $k-$染色 [即每种颜色的边的数量都相同,下略],由切边等价的定义知,每个圈一定可以写成若干个 $E_i$ 的不交并)

下面我们证明这个条件也是必要的。

(我们证明的主要思路是,证明每个 $E_i$ 都要被均匀 $k-$染色,然后就有 $k \mid \left| E_1 \right|, k \mid \left| E_2 \right|, \cdots, k \mid \left| E_\kappa \right|$,从而得到 $k \mid \gcd \left( \left| E_1 \right|, \left| E_2 \right|, \cdots, \left| E_\kappa \right| \right)$)

对于固定的 $k$,固定一种颜色 $c \in \left[ 1, k \right]$,用 $y_i$ 表示等价类 $E_i$ 中颜色为 $c$ 的边的数量,$x_i = k \cdot y_i - \left| E_i \right|$。如果我们能证明对于每个 $i \in \left[ 1, \kappa \right]$,都有 $k \cdot y_i = \left| E_i \right|$ ($x_i = 0$),那么自然就能得到结论 ($k \mid \left| E_i \right|$)。

再证明主定理之前,我们首先要证明一个引理:

(引理) 设 $b_1, b_2, \cdots, b_n \in \left\{ 0, 1 \right\}$,则 $\displaystyle \sum_{i=1}^n b_i - \sum_{1 \leq i < j \leq n} \left( b_i \oplus b_j \right) + \sum_{1 \leq i < j < k \leq n} \left( b_i \oplus b_j \oplus b_k \right) - \cdots + \left( -1 \right)^{k-1} \sum_{1 \leq i_1 < i_2 < \cdots < i_k \leq n} \left( b_{i_1} \oplus b_{i_2} \oplus \cdots \oplus b_{i_k} \right) + \cdots + \left( -1 \right)^{n-1} \left( b_1 \oplus b_2 \oplus \cdots \oplus b_n \right) = 2^{n-1} b_1 b_2 \cdots b_n$

证明

定义集合 $U = \left\{ 1, 2, \cdots, n \right\}, S = \left\{ i \mid b_i = 1, i \in U \right\}$,则对于 $T \subseteq U$,有 $\displaystyle \bigoplus_{i \in T} b_i = \left| T \cap S \right| \bmod 2$。于是有 \begin{align*} \sum_{T \subseteq U} \left( -1 \right)^{\left| T \right| - 1} \bigoplus_{i \in T} b_i &= \sum_{T \subseteq U} \left( -1 \right)^{\left| T \right| - 1} \left( \left| T \cap S \right| \bmod 2 \right) \\ &= \sum_{T \subseteq U} \left( -1 \right)^{\left| T \right| - 1} \cdot \frac {1 - \left( -1 \right)^{\left| T \cap S \right|}} 2 \\ &= \frac 12 \left( - \sum_{T \subseteq U} \left( -1 \right)^{\left| T \right|} + \sum_{T \subseteq U} \left( -1 \right)^{\left| T \right| + \left| T \cap S \right|} \right) \\ &= \frac 12 \sum_{T \subseteq U} \left( -1 \right)^{\left| T \right| + \left| T \cap S \right|} \\ &= \frac 12 \sum_{T \subseteq U} \left( -1 \right)^{\left| T \cap \bar S \right|} \\ &= \frac 12 \cdot 2^n \cdot \left[ \bar S = \varnothing \right] \tag{*} \label * \\ &= 2^{n-1} \cdot \left[ S = U \right] \\ &= 2^{n-1} b_1 b_2 \cdots b_n \end{align*}

其中 $\eqref *$ 一步利用了 [vijos #5]集合对称差卷积 中的恒等式 (这其实也是 FWT 的经典理论)。

有了这个引理后,我们就可以证明主定理了。注意里面会涉及到一点线性代数中的知识。

(主定理) $x_1 = x_2 = \cdots = x_\kappa = 0$

证明

对于每个圈 $C$,它可以写成若干个 $E_i$ 的不交并。设 $C = E_{i_1} \cup E_{i_2} \cup \cdots \cup E_{i_\gamma}$,则我们定义一个 $k$ 维 $0/1$ 行向量 $\boldsymbol v = \begin{bmatrix} v_1 & v_2 & \cdots & v_\kappa \end{bmatrix}$,满足只有 $v_{i_1} = v_{i_2} = \cdots = v_{i_\gamma} = 1$。

由题目条件可知,$k \cdot \left( y_{i_1} + y_{i_2} + \cdots + y_{i_\gamma} \right) = \left| C \right| = \left| E_{i_1} \right| + \left| E_{i_2} \right| + \cdots + \left| E_{i_\gamma} \right|$,因此有 $$ x_{i_1} + x_{i_2} + \cdots + x_{i_\gamma} = 0 $$

等价地,记列向量 $\boldsymbol x = \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_\kappa \end{bmatrix}$,则有 $$ \boldsymbol v \cdot \boldsymbol x = 0 $$

由于每个圈都能被表示成一个 $0/1$ 向量,且两个圈在 $\mathbb F_2$ 下的和仍然是一个或多个不交圈,因此我们可以考虑 $G$ 的圈空间 $V$ (维度恰为 $\beta = \left| E \right| - \left| V \right| + 1$)。

设 $V$ 中所有 $2^\beta$ 个向量分别为 $\boldsymbol u_0, \boldsymbol u_1, \cdots, \boldsymbol u_{2^\beta-1}$ (ps: 注意这里的向量是在 $\mathbb F_2$ 中的),则我们可以得到一个 $2^\beta \times \kappa$ 的线性方程组:$$ \begin{bmatrix} u_{01} & u_{02} & u_{03} & \cdots & u_{0\kappa} \\ u_{11} & u_{12} & u_{13} & \cdots & u_{1\kappa} \\ u_{21} & u_{22} & u_{23} & \cdots & u_{2\kappa} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ u_{2^\beta-1, 1} & u_{2^\beta-1, 2} & u_{2^\beta-1, 3} & \cdots & u_{2^\beta-1, \kappa} \end{bmatrix} \cdot \begin{bmatrix} x_1 \\ x_2 \\ x_3 \\ \vdots \\ x_\kappa \end{bmatrix} = \begin{bmatrix} 0 \\ 0 \\ 0 \\ \vdots \\ 0 \end{bmatrix}$$

用分块矩阵的写法就是 $$ \begin{bmatrix} \boldsymbol u_0 \\ \boldsymbol u_1 \\ \boldsymbol u_2 \\ \vdots \\ \boldsymbol u_{2^\beta-1} \end{bmatrix} \cdot \boldsymbol x = \mathbf 0_{2^\beta} \tag 1 \label 1 $$

(ps: 这里一个比较容易陷入的误区就是,$\eqref 1$ 式是在实数域下的等式,而这些向量 $\boldsymbol u_0, \boldsymbol u_1, \cdots, \boldsymbol u_{2^\beta-1}$ 是在 $\mathbb F_2$ 意义下构造出来的 $0/1$ 向量 "扩域" 到实数的结果。因此这些尽管这些向量在 $\mathbb F_2$ 下的秩显然是 $\beta$,但是在 $\mathbb R$ 上是不一定的 [而且由后续的证明知它的秩应当为 $\kappa$])


首先,由于任意两个 $x_i$ (列) 都属于不同的 $E_i$,因此它们切边等价。因此至少存在一个圈 (行),满足它包含两组 $E_i$ 中的恰好一个 (其中一列为 $1$,另一列为 $0$)

事实上,我们任取圈空间 $V$ 的一组基 $B = \left[ \boldsymbol v_1, \boldsymbol v_2, \cdots, \boldsymbol v_\beta \right]$,我们可以将上述条件加强为:存在一个圈 (行) $C \in B$,满足它包含两组 $E_i$ 中的恰好一个 (其中一列为 $1$,另一列为 $0$)

我们可以适当调整 $\boldsymbol u_i$ 的顺序,使得 $\left[ \boldsymbol u_0, \boldsymbol u_1, \cdots, \boldsymbol u_{\beta - 1} \right] = \left[ \boldsymbol v_1, \boldsymbol v_2, \cdots, \boldsymbol v_\beta \right]$。于是,考虑上述矩阵的子矩阵 $$ \mathbf P = \begin{bmatrix} v_{11} & v_{12} & \cdots & v_{1\kappa} \\ v_{21} & v_{22} & \cdots & v_{2\kappa} \\ \vdots & \vdots & \ddots & \vdots \\ v_{\beta1} & v_{\beta2} & \cdots & v_{\beta\kappa} \end{bmatrix} $$

青色结论知,矩阵 $\mathbf P$ 的 $\kappa$ 个列向量互不相同。当然,仍然有 $\mathbf P \cdot \boldsymbol x = \mathbf 0_\beta$。

设 $U = \left\{ 1, 2, \cdots, \beta \right\}$。则对于 $\forall S = \left\{ i_1, i_2, \cdots \right\} \subseteq U$,设 $\boldsymbol w = \boldsymbol v_{i_1} \mathbin{\&} \boldsymbol v_{i_2} \mathbin{\&} \cdots$ (这里 $\mathbin{\&}$ 表示 $\mathbb F_2$ 中逐分量与),由引理知,$\boldsymbol w$ 是若干个 $\boldsymbol u_i$ 在 $\mathbb R$ 上的线性组合,因此有 $$ \boldsymbol w \cdot \boldsymbol x = 0 $$


对于每个 $1 \leq j \leq \kappa$,我们定义 $A_j = \left\{ i \mid v_{ij} = 1, i \in U \right\}$。则之前的结论可以写成 $A_1, A_2, \cdots, A_\kappa$ 互不相同

适当调整 $E_j$ 的顺序,使得 $A_1, A_2, \cdots, A_\kappa$ 是子集偏序的一个拓扑序 (即如果 $A_i \subseteq A_j$ 则 $i \leq j$)。我们按照 $j = \kappa, \kappa - 1, \cdots, 2, 1$ 的顺序归纳证明 $x_j = 0$。

设已经有 $x_{j + 1} = x_{j + 2} = \cdots = x_\kappa = 0$。下证明 $x_j = 0$。

设 $A_j = \left\{ i_1, i_2, \cdots \right\} \subseteq U$,则考虑 $\boldsymbol w = \boldsymbol v_{i_1} \mathbin{\&} \boldsymbol v_{i_2} \mathbin{\&} \cdots$。

设 $\xi$ 满足 $w_\xi = 1$,则由定义知 $v_{i_1\xi} = v_{i_2\xi} = \cdots = 1 \Rightarrow i_1, i_2, \cdots \in A_\xi \Rightarrow A_j \subseteq A_\xi \Rightarrow j \leq \xi$。

由上结论知 $\boldsymbol w \cdot \boldsymbol x = 0$ 和 $x_{j + 1} = x_{j + 2} = \cdots = x_\kappa = 0$ 知 $x_j = 0$。

综上,有 $x_1 = x_2 = \cdots = x_\kappa = 0$,结论成立。

于是主定理成立。从而对于 $2-$边连通图 $G$,一个 $k$ 可行当且仅当 $k \mid \gcd \left( \left| E_1 \right|, \left| E_2 \right|, \cdots, \left| E_\kappa \right| \right)$。

对于 $G$ 有多个 $2-$边连通分量的情形,则可以对每个 $2-$边连通分量,求出使得该连通分量能被 $k-$染色的充要条件 $k \mid c$ ($c$ 为某个常数),因此只需要把最后所有连通分量的 $c$ 取 $\gcd$ 即得一般图 $G$ 的充要条件。

设最终的充要条件为 $k \mid c$ ($c \in \mathbb N^*$),因此只需要输出 $c$ 的所有正因子即可通过。


关于如何求 "切边等价" 的关系的等价类,也有很多种方法:

  1. 定理 1,知 $\left( e_1, e_2 \right)$ 切边等价 $\Leftrightarrow \left( e_1, e_2 \right)$ 是切边对。

    因此对于 $2-$边连通图 $G$,只需要枚举 $e_1$,找到 $G \setminus \left\{ e_1 \right\}$ 中所有的桥边,它们与 $e_1$ 共同构成了一个切边等价类。

  2. 定理 2,知一个切边等价类就是集合 $C$ 的等价类。

    但是集合 $C$ 相等很难判断,我们可以利用和这道题类似的 (随机化) Hash 的思想来判断两个集合是否相等。

时间复杂度 $O \left( m \left( n + m \right) \right)$ 或更优。

代码

#include <bits/stdc++.h>
#define ad(x) (((x - 1) ^ 1) + 1)
using std::cin;
using std::cout;

typedef long long ll;
const int N = 2054, M = N * 2;

struct edge {
	int u, v;
	edge (int u0 = 0, int v0 = 0) : u(u0), v(v0) {}
} e[M];

int V, E, C, Es = 0;
int first[N], next[M];
int cnt = 0, id[N], low[N];
int col[M], count[N];
bool banned[M];

inline void down(int &x, const int y) {x > y ? x = y : 0;}

inline void addedge(int u, int v) {
	e[++Es] = edge(u, v), next[Es] = first[u], first[u] = Es;
	e[++Es] = edge(v, u), next[Es] = first[v], first[v] = Es;
}

void dfs(int x, int px = 0) {
	int i, y;
	id[x] = low[x] = ++cnt;
	for (i = first[x]; i; i = next[i]) if (!banned[i] && ~col[i]) {
		if (!id[y = e[i].v]) {
			dfs(y, x), down(low[x], low[y]);
			if (id[x] < low[y]) assert(!col[i]), col[i] = col[ad(i)] = C;
		} else if (y != px)
			down(low[x], id[y]);
	}
}

inline void coloring() {
	cnt = 0, memset(id, 0, (V + 1) << 2);
	for (int i = 1; i <= V; ++i) if (!id[i]) dfs(i);
}

int main() {
	int i, u, v, d = 0;
	std::ios::sync_with_stdio(false), cin.tie(NULL);
	cin >> V >> E;
	for (i = 1; i <= E; ++i) cin >> u >> v, addedge(u, v);
	C = -1, coloring(), C = 0;
	for (i = 1; i <= Es; i += 2) if (!col[i])
		banned[i] = banned[i + 1] = true,
		col[i] = col[i + 1] = ++C, coloring(),
		banned[i] = banned[i + 1] = false;
	for (i = 1; i <= Es; i += 2) ++count[col[i]];
	for (i = 1; i <= C; ++i) d = std::__gcd(d, count[i]);
	for (i = 1; i < d; ++i) if (!(d % i)) cout << i << ' ';
	cout << d << '\n';
	return 0;
}

坑1:注意最开始一点要把桥边先去除掉,不要统计到任何等价类中,否则会造成答案变少。

坑2:无向边枚举的时候注意方向问题。