淺談LGV引理


\(LGV\)引理

定義\(w(P)\)為有向路徑\(P\)所有邊權的乘積,並定義\(f(a,b)\)表示\(a\rightarrow b\)所有有向路徑邊權乘積之和,即:

\[f(a,b)=\sum_{P:a\rightarrow b}w(P) \]

列出一個矩陣:

\[M=\begin{bmatrix} f(a_1,b_1)&f(a_1,b_2)&\cdots&f(a_1,b_n)\\ f(a_2,b_1)&f(a_2,b_2)&\cdots&f(a_2,b_n)\\ \vdots&\vdots&\ddots&\vdots\\ f(a_n,b_1)&f(a_n,b_2)&\cdots&f(a_n,b_n) \end{bmatrix} \]

對於\(A\rightarrow B\)的一個不交路徑集合\(P_{1\sim n}\),其中\(P_i\)表示從\(a_i\)\(b_{\sigma(P)_i}\)的一條路徑(\(\sigma(P)\)\(P\)對應的一個排列)。

然后對一個排列\(\sigma\)定義\(sgn(\sigma)\),當\(\sigma\)中逆序對個數為偶數時\(sgn(\sigma)=1\),為奇數時\(sgn(\sigma)=-1\)

則滿足:

\[\det(M)=\sum_{P:A\rightarrow B}sgn(\sigma(P))\prod_{i=1}^nw(P_i) \]

路徑不交問題

一種比較常見的題型,是求從每個\(a_i\)\(b_i\),在滿足路徑不交的前提下,所有方案中路徑邊權乘積之和

則根據行列式的計算式發現:

\[\det(M)=\sum_{\sigma}sgn(\sigma)\prod_{i=1}^nf(a_i,b_{\sigma(i)}) \]

考慮如果兩個人的路徑相交了,我們可以將相交后的部分取反,就相當於這兩人分別走到了對方的終點去。

因此,我們可以把這當作一個容斥問題看待,即枚舉一個排列\(\sigma\)表示每個人走到了誰的終點去。

然后發現容斥系數是\(sgn(\sigma)\),也就是說這個\(\det(M)\)其實就是答案。

模板題解法

  • 給定一張\(n\times m\)的棋盤,每次只能向右或向下走一步。
  • \(m\)個棋子,分別要從\((a_i,1)\)走到\((b_i,n)\),求路徑不交的方案數。
  • \(n\le10^6,m\le100\)

超級簡化版。

相當於每條路徑邊權都是\(1\),那么\(f(a_i,b_j)\)實際上就是從\((a_i,1)\)走到\((b_j,n)\)的方案數。

這應該算是個經典組合數問題,顯然就是\(C_{n-1+b_j-a_i}^{n-1}\)

代碼:\(O(n+m^3)\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000000
#define M 100
#define X 998244353
#define C(x,y) (1LL*Fac[x]*IFac[y]%X*IFac[(x)-(y)]%X)//組合數
using namespace std;
int n,m,a[M+5],b[M+5];I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
int Fac[2*N+5],IFac[2*N+5];I void InitFac(CI S)//預處理階乘和階乘逆元
{
	RI i;for(Fac[0]=i=1;i<=S;++i) Fac[i]=1LL*Fac[i-1]*i%X;
	for(IFac[i=S]=QP(Fac[S],X-2);i;--i) IFac[i-1]=1LL*IFac[i]*i%X;
}
namespace G//高斯消元
{
	int a[M+5][M+5];I int Det(CI n)//求解行列式
	{
		RI i,j,k,t,s=1;for(i=1;i<=n;s=1LL*s*a[i][i]%X,++i)
		{
			if(!a[i][i]) {for(s=X-s,j=i+1;j<=n&&!a[j][i];++j);for(k=i;k<=n;++k) swap(a[i][k],a[j][k]);}
			for(j=i+1;j<=n;++j) for(t=1LL*(X-a[j][i])*QP(a[i][i],X-2)%X,k=i;k<=n;++k) a[j][k]=(a[j][k]+1LL*t*a[i][k])%X;
		}return s;
	}
}
int main()
{
	RI Tt,i,j;InitFac(N<<1),scanf("%d",&Tt);W(Tt--)
	{
		for(scanf("%d%d",&n,&m),i=1;i<=m;++i) scanf("%d%d",a+i,b+i);
		for(i=1;i<=m;++i) for(j=1;j<=m;++j) G::a[i][j]=a[i]<=b[j]?C(n-1+b[j]-a[i],n-1):0;//組合數計算路徑數
		printf("%d\n",G::Det(m));
	}return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM