BEST 定理
BEST 定理
记 \(G\) 是一个有向欧拉图,\(t^{in}(G,k)\) 表示图 \(G\) 以 \(k\) 点为根的内向生成树个数,\(\varepsilon(G)\) 表示图 \(G\) 的欧拉回路数,\(\deg(v)\) 表示点 \(v\) 的入度(等于出度),有:
\[\varepsilon(G)=t^{in}(G,k)\prod_{v\in V}(\deg(v)-1)!
\]
其中 \(k\) 可以为任意顶点,含义为欧拉回路起点。注意这里欧拉回路是循环同构的。图中不应包含零度点。
\(t^{in}(G,k)\) 使用矩阵树定理求即可。
证明
我们只需将以 \(k\) 为起点的欧拉回路与以 \(k\) 为根的内向生成树联系起来即可。首先我们将公式写作:
\[\varepsilon(G)\deg(k)=t^{in}(G,k)\deg(k)!\prod_{v\in V\setminus\{k\}}(\deg(v)-1)!
\]
该公式的构造意为:
- 内向生成树的树边就是子节点在欧拉回路上最后一次走的出边。
- 根节点的所有出边任意排列方案数 \(\deg(k)!\)。
- 非根节点的所有非树出边任意排列方案数 \(\prod_{v\in V\setminus\{k\}}(\deg(v)-1)!\)。
- 对于同一个欧拉回路,其中 \(k\) 节点出现了 \(\deg(k)\) 次(终点即为起点不另算),每一个位置都会被算一遍,故而会算重 \(\deg(k)\) 次。
只需证明这样构造出了一个双射即可。
我们先证明每条欧拉回路都唯一对应上述生成树和出边顺序。
唯一对应出边顺序是显然的,只需证明非根节点的最后一条出边能形成一个内向生成树。若不能则必然成不包含根节点的环且终止在非根节点上,欧拉回路必然在起点中止,矛盾,得证。
接下来我们证明每组生成树和出边顺序都唯一对应一条欧拉回路。
首先我们直接按照给定的出边顺序模拟,由于是欧拉图入度等于出度所以最后必然能走回到根节点,只需证明每条边都会被走过即可。我们归纳法证明:首先这条边不可能是根节点的出边;其次,一个点有出边没被走过,当且仅当其有入边没被走过,并且其树边必然没被走过,故而其树上父节点也有出边剩余,最后会推到根节点,矛盾,不成立。
证毕。
习题
P5807 【模板】BEST 定理 / Which Dreamed It
要先判是不是欧拉图。做之前要把所有零度点删掉。
然后注意要求了从 \(1\) 出发,要判一下是不是只有 \(1\) 所在连通块有边。
这道题欧拉回路并不循环同构,故而要乘上 \(\deg(1)\)。
然后终于可以愉快地套 BEST 定理了。
code
const int N=105;
int n;
int dg[N],id[N];
int G[N][N];
vec<vec<mint>> g,d,l;
inline mint det(vec<vec<mint>> v){
int n=v.size();mint res=1;
repl(i,0,n)repl(j,i+1,n){
if(!v[i][i].x)swap(v[i],v[j]),res*=-1;
else{
mint d=v[j][i]/v[i][i];
repl(k,0,n)v[j][k]-=d*v[i][k];
}
}
repl(i,0,n)res*=v[i][i];
return res;
}
int uid[N],idx;
mint fc[3141593];
inline void Main(){
cin>>n;
repl(i,0,n)id[i]=0,uid[i]=-1;idx=0;
repl(i,0,n)repl(j,0,n)G[i][j]=0;
repl(i,0,n){
cin>>dg[i];if(dg[i])uid[i]=idx++;
rep(h,1,dg[i]){
int x;cin>>x;--x;
++G[i][x],++id[x];
}
}
repl(i,0,n)if(dg[i]!=id[i])return put(0),void();
if(!idx)return put(1),void();
if(!~uid[0])return put(0),void();
g.clear(),d.clear(),l.clear();
g.resize(idx,vec<mint>(idx)),d=g;
l.resize(idx-1,vec<mint>(idx-1));
mint ans=1;
repl(i,0,n)if(~uid[i]){
ans*=fc[dg[i]-1];
d[uid[i]][uid[i]]=dg[i];
repl(j,0,n)if(G[i][j])g[uid[i]][uid[j]]=G[i][j];
}
n=idx;
repl(i,0,n-1)repl(j,0,n-1)l[i][j]=d[i+1][j+1]-g[i+1][j+1];
ans*=det(l);
ans*=d[0][0];
put(ans);
}

浙公网安备 33010602011771号