zoukankan      html  css  js  c++  java
  • 【bzoj4596】黑暗前的幻想乡

    Portal -->bzoj4596

    Solution

      这题的话。。因为(N)比较小啊所以我们可以大力容斥(尽管实际算下来复杂度有点爆炸不过实测是能过的qwq)

      枚举包含了哪些颜色的边,每次重新填矩阵然后矩阵树定理高消求一波行列式然后乘上个容斥系数加到答案里面去就好了

      关于容斥原理这个东西。。(怎么感觉快忘光了)

      其实也不用想太多,反正是从最终状态(包含所有的,在这里是包含(n-1)种)开始往后推符号为一正一负就好了:

    [ans=ans_{n-1}-ans_{n-2}+ans_{n-3}... ]

      然后代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=20,MOD=1e9+7;
    struct xxx{
    	int x,y,nxt;
    }a[100010];
    int A[N][N],h[N],ok[N];
    int n,m,tot,ans;
    void add(int x,int y,int col);
    int solve(int n);
    int Abs(int x){return x>0?x:-x;}
    bool in(int st,int x){return st>>(x-1)&1;}
    int work();
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	int x,y;
    	scanf("%d",&n);
    	memset(h,-1,sizeof(h));
    	tot=0;
    	for (int i=1;i<n;++i){
    		scanf("%d",&m);
    		for (int j=1;j<=m;++j){
    			scanf("%d%d",&x,&y);
    			add(x,y,i);
    		}
    	}
    	ans=0;
    	int all=1<<n-1,cnt,tmp,n1;
    	for (int i=1;i<all;++i){
    		memset(A,0,sizeof(A));
    		cnt=0;
    		for (int j=1;j<n;++j)
    			if (in(i,j)){
    				for (int k=h[j];k!=-1;k=a[k].nxt){
    					x=a[k].x; y=a[k].y;
    					++A[x][x]; ++A[y][y];
    					--A[x][y]; --A[y][x];
    				}
    			}
    			else ++cnt;
    		tmp=solve(n-1);
    		if (cnt&1) 
    			ans=(ans-tmp+MOD)%MOD;
    		else 
    			ans=(ans+tmp)%MOD;
    	}
    	printf("%d
    ",ans);
    }
    
    void add(int x,int y,int col){
    	a[++tot].x=x; a[tot].y=y; a[tot].nxt=h[col]; h[col]=tot;
    }
    
    int solve(int n){
    	int id,ret=1,tmp;
    	for (int i=1;i<=n;++i){
    		for (id=i;id<=n;++id)
    			if (A[id][i]) break;
    		if (id>n) continue;
    		if (id!=i){
    			ret=-ret;
    			for (int j=i+1;j<=n;++j) swap(A[i][j],A[id][j]);
    		}
    		for (int j=i+1;j<=n;++j){
    			while (A[j][i]){
    				tmp=A[j][i]/A[i][i];
    				for (int k=1;k<=n;++k)
    					A[j][k]=(1LL*A[j][k]+MOD-1LL*tmp*A[i][k]%MOD)%MOD;
    				if (A[j][i]==0) break;
    				ret=-ret;
    				for (int k=1;k<=n;++k)
    					swap(A[j][k],A[i][k]);
    			}
    		}
    	}
    	for (int i=1;i<=n;++i)
    		ret=1LL*ret*A[i][i]%MOD;
    	return (ret+MOD)%MOD;
    }
    
  • 相关阅读:
    CF1202F You Are Given Some Letters...
    CF1178E Archaeology
    PTA (Advanced Level) 1005 Spell It Right
    PTA (Advanced Level) 1004 Counting Leaves
    Qt5——从零开始的Hello World教程(Qt Creator)
    PTA (Advanced Level) 1003 Emergency
    PTA (Advanced Level) 1002 A+B for Polynomials
    HDU 1272 小希的迷宫
    FZU 2150 Fire Game
    HihoCoder
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9226226.html
Copyright © 2011-2022 走看看