zoukankan      html  css  js  c++  java
  • 【Matrix-tree定理】【BEST Theorem】hdu6064 RXD and numbers

    题意:给你一张有向图,求从1出发,回到1的欧拉回路数量。

    先特判掉欧拉回路不存在时的情况。

    看这个吧:http://blog.csdn.net/yuanjunlai141/article/details/76691680。

    这是求有向图(以某个点为根的)生成外向树的方法。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const ll MOD=998244353ll;
    int n,a[405][405],chu[405],ru[405];
    ll A[405][405],jc[200005];
    int sum;
    bool vis[405];
    void dfs(int U){
    	++sum;
    	vis[U]=1;
    	for(int i=1;i<=n;++i){
    		if(a[U][i] && !vis[i]){
    			dfs(i);
    		}
    	}
    }
    ll Quick_Pow(ll a,ll p){
    	if(!p){
    		return 1ll;
    	}
    	ll res=Quick_Pow(a,p>>1);
    	res=res*res%MOD;
    	if((p&1ll)==1ll){
    		res=a%MOD*res%MOD;
    	}
    	return res;
    }
    ll guass_jordan()
    {
    	if(n==2){
    		return A[2][2];
    	}
    	for(int i=2;i<=n;++i){
    		for(int j=2;j<=n;++j){
    			A[i-1][j-1]=A[i][j];
    		}
    	}
        ll res=1;
        for(int i=1;i<n;++i)
          {
            int pivot=i;
            for(int j=i+1;j<n;++j)
              if(A[j][i]){
              	pivot=j;
              	break;
              }
            swap(A[i],A[pivot]);
            if(i!=pivot){
            	res=res*(MOD-1ll)%MOD;
            }
            if(A[i][i]==0){
                return 0;
            }
            ll ni=Quick_Pow(A[i][i],MOD-2ll);
            for(int j=i+1;j<n;++j)
              A[i][j]=A[i][j]*ni%MOD;
            res=res*A[i][i]%MOD;
            for(int j=1;j<n;++j)
              if(i!=j)
                for(int k=i+1;k<n;++k)
                  A[j][k]=(A[j][k]-A[j][i]*A[i][k]%MOD+MOD)%MOD;
          }
        return res;
    }
    int main(){
    //	freopen("hdu6064.in","r",stdin);
    	jc[0]=1;
    	for(int i=1;i<=200000;++i){
    		jc[i]=jc[i-1]*(ll)i%MOD;
    	}
    	int zu=0;
    	while(scanf("%d",&n)!=EOF){
    		++zu;
    		printf("Case #%d: ",zu);
    		if(n==1){
    			puts("1");
    			continue;
    		}
    		memset(A,0,sizeof(A));
    		memset(chu,0,sizeof(chu));
    		memset(ru,0,sizeof(ru));
    		for(int i=1;i<=n;++i){
    			for(int j=1;j<=n;++j){
    				scanf("%d",&a[i][j]);
    			}
    		}
    		bool flag=1;
    		for(int i=1;i<=n;++i){
    			for(int j=1;j<=n;++j){
    				ru[i]+=a[j][i];
    				chu[i]+=a[i][j];
    				if(j!=i){
    					A[i][i]=(A[i][i]+(ll)a[j][i])%MOD;
    					if(a[i][j]){
    						A[i][j]=MOD-a[i][j];
    					}
    				}
    			}
    			if(ru[i]!=chu[i]){
    				flag=0;
    				break;
    			}
    		}
    		if(!flag){
    			puts("0");
    			continue;
    		}
    		sum=0;
    		memset(vis,0,sizeof(vis));
    		dfs(1);
    		if(sum!=n){
    			puts("0");
    			continue;
    		}
    		ll ans=guass_jordan()*jc[ru[1]]%MOD;
    		for(int i=2;i<=n;++i){
    			ans=ans*jc[(ru[i]-1)]%MOD;
    		}
    		for(int i=1;i<=n;++i){
    			for(int j=1;j<=n;++j){
    				ans=ans*Quick_Pow(jc[a[i][j]],MOD-2ll)%MOD;
    			}
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
  • 相关阅读:
    android基础开发之一setContentView用法
    setContentView( )方法
    如何使用andriod的布局标签
    也谈layout_gravity和gravity的用法
    SlidingMenu第二篇 --- SlidingMenu常用属性介绍
    SlidingMenu第一篇 --- 导入SlidingMenu库
    JS----对象的合并与克隆
    angular2 ----字符串、对象、base64 之间的转换
    WebStorm过期解决方法
    JavaScript--鼠标滚动改变图片大小
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7630380.html
Copyright © 2011-2022 走看看