ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[CF578F] Mirror Box

2021-08-09 19:01:54  阅读:219  来源: 互联网

标签:Box ch 奇数 点图 奇偶性 CF578F 偶数 Mirror define


\(\text{Problem}:\)Mirror Box

\(\text{Solution}:\)​

较为显然的是如果 /\ 围出了一个环,就无解。

考虑光线会从相邻的边界段射出,这说明两个边界段的奇偶性相同的非重合端点(此处认为一个网格上点 \((i,j)\)​ 的奇偶性为 \((i+j)\%2\)​ 的取值,原图有 \((n+1)\times(m+1)\) 个点)被 /\ 相连。

而上面连通的点 \((i_{1},j_{1}),(i_{2},j_{2})\) 的奇偶性相同,且 /\ 连接的两点奇偶性也相同,这提示在合法的网格中,奇数点偶数点相连形成一棵树。而当网格图上的 * 被确定时,一定不存在奇数点和偶数点能同时形成一棵树,原因显然。这提示我们对奇数点和偶数点分别算出答案,相加即可。

现在考虑有 * 的情况。不难发现,将已确定连通的点缩点后,可以把网格图转化为两张无向图,需要对每张无向图求出生成树个数。利用矩阵树定理即可求解。

注意首先要判断给定的 /\ 是否已经构成环,以及奇数点图与偶数点图是否连通。若满足以上情况,对应的奇数点图或偶数点图的答案显然为 \(0\)​​​。时间复杂度 \(O(nm\cdot\alpha(nm)+K^3)\)​​。

\(\text{Code}:\)

#include <bits/stdc++.h>
//#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=210;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,m,Mod; char s[N][N];
int f[N*N],id[N*N],cnt,a[N][N];
inline int Id(int x,int y) { return (x-1)*(m+1)+y; }
inline void Init()
{
	for(ri int i=1;i<=n+1;i++)
	for(ri int j=1;j<=m+1;j++)
	f[Id(i,j)]=Id(i,j);
}
inline int Find(int x) { return f[x]^x?f[x]=Find(f[x]):x; }
inline void Merge(int x,int y)
{
	int fx=Find(x), fy=Find(y);
	if(fx==fy) { puts("0"); exit(0); }
	f[fx]=fy;
}
inline int Det()
{
	int res=1;
	for(ri int i=1;i<cnt;i++)
	{
		for(ri int j=i+1;j<cnt;j++)
		{
			while(a[i][i])
			{
				int w=a[j][i]/a[i][i];
				for(ri int k=i;k<cnt;k++) a[j][k]=(a[j][k]-1ll*w*a[i][k]%Mod+Mod)%Mod;
				for(ri int k=1;k<cnt;k++) swap(a[i][k],a[j][k]);
				res=-res;
			}
			for(ri int k=1;k<cnt;k++) swap(a[i][k],a[j][k]);
			res=-res;
		}
	}
	for(ri int i=1;i<cnt;i++) res=1ll*res*a[i][i]%Mod;
	return (res+Mod)%Mod;
}
inline int Solve(int tp)
{
	cnt=0;
	memset(a,0,sizeof(a));
	for(ri int i=1;i<=n+1;i++)
	{
		for(ri int j=1;j<=m+1;j++)
		{
			if((i+j)%2==tp && Id(i,j)==Find(Id(i,j))) id[Id(i,j)]=++cnt;
		}
	}
	for(ri int i=1;i<=n;i++)
	{
		for(ri int j=1;j<=m;j++)
		{
			if(s[i][j]=='*')
			{
				int x,y;
				if((i+j)%2==tp) x=id[Find(Id(i,j))], y=id[Find(Id(i+1,j+1))];
				else x=id[Find(Id(i+1,j))], y=id[Find(Id(i,j+1))];
				if(x==y) continue;
				a[x][x]++, a[y][y]++, a[x][y]--, a[y][x]--;
			}
		}
	}
	return Det();
}
signed main()
{
	n=read(), m=read(), Mod=read();
	for(ri int i=1;i<=n;i++) scanf("%s",s[i]+1);
	Init();
	for(ri int i=1;i<=n;i++)
	{
		for(ri int j=1;j<=m;j++)
		{
			if(s[i][j]=='/') Merge(Id(i+1,j),Id(i,j+1));
			if(s[i][j]=='\\') Merge(Id(i,j),Id(i+1,j+1));
		}
	}
	printf("%d\n",(Solve(0)+Solve(1))%Mod);
	return 0;
}

标签:Box,ch,奇数,点图,奇偶性,CF578F,偶数,Mirror,define
来源: https://www.cnblogs.com/zkdxl/p/15120058.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有