【noi复习】LGV引理
LGV 引理 只适用于 有向无环图。
记起点集合为 \(A=\{a_1,a_2,\cdots a_n\}\),终点集合为 \(B=\{b_1,b_2\cdots b_n\}\),两个集合大小均为 \(n\)。
对于一条路径 \(P=\displaystyle\{u_1,w_{u_1u_2},u_2,\cdots u_t \}\),用 \(\omega(P)\) 表示 \(P\) 上所有边权之积
记 \(e(u,v)\) 表示从 \(u\) 到 \(v\) 所有路径的 \(\omega\) 之和
定义两条路径“不相交”为不存在公共顶点。
定义一组“从起点集合 \(A\) 出发,结束于终点集合 \(B\) 的路径”为选定一个排列 \(\sigma_1,\cdots\sigma_n\) ,让 \(a_i\) 走向 \(\displaystyle b_{\sigma_i}\),这 \(n\) 条路径构成的集合,记该集合为 \(S\) ,\(a_i\) 走向 \(b_{\sigma_i}\) 的路径为 \(S_i\) 。
定义一组 “\(A\rarr B\) 的不相交路径”为如上的 \(S\) ,且 \(S_i\) 和 \(S_j\) 两两不相交。
用 \(t(\sigma)\) 代表排列 \(\sigma\) 的逆序对个数。
LGV 引理如下:
其中 \(\sum\limits_{S:A\rightarrow B}\) 表示满足上文要求的 \(A\rightarrow B\) 的每一组不相交路径 \(S\)。
例题
P6657 【模板】LGV 引理
题意:
有一个 \(n\times n\) 的棋盘,左下角为 \((1,1)\),右上角为 \((n,n)\),若一个棋子在点 \((x,y)\),那么走一步只能走到 \((x+1,y)\) 或 \((x,y+1)\)。
现在有 \(m\) 个棋子,第 \(i\) 个棋子一开始放在 \((a_i,1)\),最终要走到 \((b_i,n)\)。问有多少种方案,使得每个棋子都能从起点走到终点,且对于所有棋子,走过路径上的点互不相交。输出方案数 \(\bmod\ 998244353\) 的值。
两种方案不同当且仅当存在至少一个棋子所经过的点不同。\(\{a_n\}\) 与 \(\{b_n\}\) 均从小到大排序。
题解:
容易发现的一点是,\(a_i\) 必定和 \(b_i\) 对应,否则一定会产生相交路径,因此 \(\sigma\) 唯一确定。路径计数问题一般考虑令边权均为 \(1\) ,且 \(\sigma\) 中逆序对数量为 \(0\) ,所以 \(\mathrm {RHS}=\sum_{S:A\rightarrow B} 1=\#S:A\rightarrow B\),即为所要求的答案。因此直接计算行列式的值即可,其中 \(e(a_i,b_j)\) 的值为从 \((a_i,1)\) 走到 \((b_i,n)\) 的路径条数,简单推导知其值为 \(\binom{b_i-a_i+n-1}{n-1}\) ,特别地,如果 \(b_i<a_i\) ,那么答案为 \(0\) 。
CF348D Turtles
题意:
有一个 \(n\times m\) 的格点棋盘,其中某些格子可走,某些格子不可走。从 \((x, y)\) 只能走到 \((x+1, y)\) 和 \((x, y+1)\) 的位置,求两只海龟从 \((1, 1)\) 到 \((n, m)\) 的不相交路径数对 \(10^9+7\) 取模之后的结果。\(2\le n,m\le3000\)。
题解:
两只海龟分别会经过 \((1,2)\) 和 \((2,1)\) ,以及 \((n-1,m)\) 和 \((n,m-1)\) 。注意到 \((1,2)\) 和 \((n-1,m)\) 是一组, \((2,1)\) 和 \((n,m-1)\) 是另一组,否则会有相交路径。因此不相交路径数即为:
其中 \(a_1=(1,2),b_1=(n-1,m),a_2=(2,1),b_2=(n,m-1)\)。由于某些格子不能走,使用 dp 求出方案数即可。
P7736 [NOI2021] 路径交点
题意:
给一个分层 DAG,共 \(k\) 层,起点和终点(第一层和最后一层)点的数量相同,均为 \(n_1\) ,要求路径没有公共点。问所有路径方案中,路径有偶数个交点的方案数 减去 有奇数个交点的方案数 是多少。
\(2\leq k,n_1\leq 100\)
题解:
起点终点数量相同的提示性很强,这是 LGV 引理比较特别的。
考虑如何刻画交点个数,对于两条路径 \(a_1\rarr b_1\) ,\(a_2\rarr b_2\) 而言,不妨 \(a_1<a_2\),如果 \(b_1<b_2\) 那么它们会产生偶数个交点,如果 \(b_1>b_2\) 那么它们会产生奇数个交点。那么所有路径交点个数为奇数,也就即为,设 \(a_i \rarr b_{\sigma_i}\),那么 \(t(\sigma)\) 为奇数。到这里我们突然发现,题目中奇数个交点方案数的容斥系数为 \(-1\) ,也就是 \((-1)^{t(\sigma)}\) !相对应的,偶数个交点也是如此。
由 LGV 引理,还是设边权均为 \(1\),则 \(\mathrm{RHS}\) 就是题目要我们求的东西,因此只需要求出左边行列式的值。
只需要 dp 算出起点到终点任意两点间的路径数量即可。时间复杂度 \(O(n^3)\) 。完全不需要脑子就能做。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read(){
ll x=0; bool f=1; char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=0; ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48); ch=getchar();
}
return f?x:-x;
}
inline void write(ll x){
if(x<0) x=-x,putchar('-');
if(x>9) write(x/10);
putchar('0'+x%10);
}
const ll MOD=998244353;
const ll N=209;
ll n[N],a[N][N];
ll Gauss(){
ll res=1;
for(ll i=1;i<=n[1];i++){
ll r=i;
for(ll j=i+1;j<=n[1];j++){
if(a[j][i]){
r=j;
break;
}
}
if(r!=i) (res*=MOD-1)%=MOD,swap(a[r],a[i]);
if(a[i][i]==0){
return 0;
}
for(ll j=i+1;j<=n[1];j++){
while(a[j][i]){
ll factor=a[i][i]/a[j][i];
for(ll k=i;k<=n[1];k++){
a[i][k]-=a[j][k]*factor%MOD;
a[i][k]%=MOD,a[i][k]+=MOD,a[i][k]%=MOD;
}
swap(a[j],a[i]);
(res*=MOD-1)%=MOD;
}
}
}
for(ll i=1;i<=n[1];i++){
res=(res*a[i][i])%MOD;
}
return res;
}
ll g[N][N],m[N];
void solve(){
ll k=read();
for(ll i=1;i<=k;i++){
n[i]=read();
}
for(ll i=1;i<=k-1;i++){
m[i]=read();
}
for(ll i=1;i<=n[1];i++){
a[i][i]=1;
}
for(ll i=1;i<=k-1;i++){
memset(g,0,sizeof(g));
for(ll j=1;j<=m[i];j++){
ll u=read(),v=read();
for(ll t=1;t<=n[1];t++){
g[t][v]+=a[t][u];
if(g[t][v]>=MOD) g[t][v]-=MOD;
}
}
memcpy(a,g,sizeof(g));
}
printf("%lld\n",Gauss());
}
int main(){
ll T=read();
while(T--){
solve();
}
return 0;
}

浙公网安备 33010602011771号