zoukankan      html  css  js  c++  java
  • BZOJ.4031.[HEOI2015]小Z的房间(Matrix Tree定理 辗转相除)

    题目链接

    辗转相除解行列式的具体实现?
    行列式的基本性质.

    //864kb	64ms
    //裸的Matrix Tree定理。练习一下用辗转相除解行列式。(因为模数不是质数,所以不能直接乘逆元来高斯消元。)
    //注意题目是将所有房间(这些才是点)连成一棵树,墙非节点,即行列式中只存在表示房间的点。否则就很可能无解了。。
    #include <cstdio>
    #include <algorithm>
    #define mod (1000000000)
    const int N=103,way[3]={1,0,1};
    
    int n,m,A[N][N],id[12][12];
    char mp[12][12];
    
    void Solve(int n)
    {
    	for(int i=1; i<n; ++i)
    		for(int j=1; j<n; ++j) (A[i][j]+=mod)%=mod;//先变成正的!
    	int f=1,res=1;
    	for(int j=1; j<n; ++j)
    	{
    		for(int i=j+1; i<n; ++i)
    			while(A[i][j])
    			{//利用A[j][j]将A[i][j]变为0,(A[j][j],A[i][j]) -> (a,b) -> (b,a%b).
    				int t=A[j][j]/A[i][j];
    				for(int k=j; k<n; ++k) A[j][k]=(A[j][k]-1ll*t*A[i][k]%mod+mod)%mod;
    				for(int k=j; k<n; ++k) std::swap(A[i][k],A[j][k]);
    				f^=1;//行列式是(0)否(1)变号。
    			}
    		if(!A[j][j]) {res=0; break;}
    		res=1ll*res*A[j][j]%mod;//将行列式化为下三角行列式后,对角线上的元素相乘即为行列式的值。
    	}
    	printf("%d",f?res:(mod-res)%mod);
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	int cnt=0;
    	for(int i=0; i<n; ++i) scanf("%s",mp[i]);
    	for(int i=0; i<n; ++i)
    		for(int j=0; j<m; ++j)
    			if(mp[i][j]=='.') id[i][j]=cnt++;//!
    	for(int i=0; i<n; ++i)
    		for(int j=0; j<m; ++j)
    			if(mp[i][j]=='.')
    				for(int u=id[i][j],v,xn,yn,d=0; d<2; ++d)
    					if((xn=i+way[d])<n&&(yn=j+way[d+1])<m&&mp[xn][yn]=='.')
    						v=id[xn][yn],--A[u][v],--A[v][u],++A[u][u],++A[v][v];
    	Solve(cnt);
    	return 0;
    }
    
  • 相关阅读:
    vector
    vector-back
    vector-back
    vector-begin
    vector-begin
    vector-at
    vector-at
    Vector-assign
    Vector-assign
    Vector-Constructors
  • 原文地址:https://www.cnblogs.com/SovietPower/p/8779968.html
Copyright © 2011-2022 走看看