• Codeforces 578F. Mirror Box 题解


    题目链接:F. Mirror Box

    题目大意:洛谷


    题解:令交点为点,镜子为边,那么题目中的每一条边必须有光线穿过相当于限制了这一张图中不存在环,而第一个限制,即每一条光线必须从相邻的格子内出来则要求这一张图所连成的必须是一棵树。

    对整个图的交点黑白染色,我们可以根据上面的分析得出最终满足条件的方案就是所有的黑点或者所有的白点构成了一个树,并且容易证明黑点和白点不可能同时构成树。

    所以我们可以对已知的边用并查集合并,那么对于这个图,跑一边矩阵树定里就可以了。

    时间复杂度(O(nm+k^3))(并查集近似认作为(O(1)))。

    代码:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int quick_power(int a,int b,int Mod){
    	int ans=1;
    	while(b){
    		if(b&1){
    			ans=1ll*ans*a%Mod;
    		}
    		b>>=1;
    		a=1ll*a*a%Mod;
    	}
    	return ans;
    }
    const int Maxn=105;
    int n,m,Mod;
    char s[Maxn+5][Maxn+5];
    int id[Maxn+5][Maxn+5],id_tot;
    int pos[Maxn*Maxn+5];
    int fa[Maxn*Maxn+5];
    int find(int x){
    	if(fa[x]==x){
    		return x;
    	}
    	return fa[x]=find(fa[x]);
    }
    void merge(int x,int y){
    	int fa_x=find(x),fa_y=find(y);
    	if(fa_x==fa_y){
    		return;
    	}
    	fa[fa_y]=fa_x;
    }
    struct Matrix{
    	int n;
    	int a[Maxn*5+5][Maxn*5+5];
    	void add_edge(int u,int v){
    		a[u][u]++;
    		a[v][v]++;
    		a[u][v]--;
    		a[v][u]--;
    	}
    	int solve(){
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=n;j++){
    				a[i][j]=(a[i][j]+Mod)%Mod;
    			}
    		}
    		int ans=1;
    		for(int i=1;i<n;i++){
    			int pos=i;
    			while(pos<n&&a[pos][i]==0){
    				pos++;
    			}
    			if(pos>=n){
    				continue;
    			}
    			if(pos!=i){
    				ans=Mod-ans;
    				swap(a[pos],a[i]);
    			}
    			int tmp=quick_power(a[i][i],Mod-2,Mod);
    			for(int j=i+1;j<n;j++){
    				int now=1ll*tmp*a[j][i]%Mod;
    				for(int k=i;k<n;k++){
    					a[j][k]=(a[j][k]-1ll*a[i][k]*now%Mod+Mod)%Mod;
    				}
    			}
    		}
    		for(int i=1;i<n;i++){
    			ans=1ll*ans*a[i][i]%Mod;
    		}
    		return ans;
    	}
    }g[2];
    int main(){
    	scanf("%d%d%d",&n,&m,&Mod);
    	for(int i=1;i<=n+1;i++){
    		for(int j=1;j<=m+1;j++){
    			id[i][j]=++id_tot;
    			fa[id[i][j]]=id[i][j];
    		}
    	}
    	for(int i=1;i<=n;i++){
    		scanf("%s",s[i]+1);
    		for(int j=1;j<=m;j++){
    			if(s[i][j]=='*'){
    				continue;
    			}
    			if(s[i][j]=='\'){
    				merge(id[i][j],id[i+1][j+1]);
    			}
    			else{
    				merge(id[i][j+1],id[i+1][j]);
    			}
    		}
    	}
    	for(int i=1;i<=n+1;i++){
    		for(int j=1;j<=m+1;j++){
    			if(find(id[i][j])==id[i][j]){
    				g[(i+j)&1].n++;
    				pos[id[i][j]]=g[(i+j)&1].n;
    			}
    		}
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			if(s[i][j]=='*'){
    				g[(i+j)&1].add_edge(pos[find(id[i][j])],pos[find(id[i+1][j+1])]);
    				g[(i+j+1)&1].add_edge(pos[find(id[i+1][j])],pos[find(id[i][j+1])]);
    			}
    		}
    	}
    	printf("%d
    ",(g[0].solve()+g[1].solve())%Mod);
    	return 0;
    }
    
  • 相关阅读:
    JavaScript 正则表达式中的特殊字符
    framework —— throttles(访问频率控制)
    framework —— permission(权限)
    framework —— auth认证
    算法——基础知识
    算法——解迷宫
    算法
    爬虫 ==》 同步调用
    asyncio模块
    Requests模块
  • 原文地址:https://www.cnblogs.com/withhope/p/13612170.html
Copyright © 2020-2023  润新知