您的位置:首页 > 其它

【CodePlus 2017 12 月赛】白金元首与独舞

2018-03-31 23:47 429 查看
时间限制 : 2000 MS 空间限制 : 512 MB

问题描述



样例输入

5

3 9

LLRRUDUUU

LLR.UDUUU

LLRRUDUUU

4 4

LLRR

L.LL

RR.R

LLRR

4 3

LRD

LUL

DLU

RDL

1 2

LR

2 2

..

..

样例输出

3

8

0

1

192

提示



题解

显然,原图中有环就是无解的情况。我们把花园外看成一个节点,每个‘.’看成一个节点,然后把各节点按可能的到达关系连边,最后得到一张有向图。那么我们要求的即为以花园外的虚拟点为根的生成树个数。有向图生成树计数方法为:基尔霍夫矩阵只记每个点的出度,最后求其去掉树根后的行列式。

代码

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=505;
ll T,n,m,tot,cnt,fa[maxn*maxn],id[maxn][maxn];
ll End[maxn*maxn],Next[maxn*maxn],Last[maxn*maxn];
ll bl[maxn*maxn],G[maxn][maxn];
char s[maxn][maxn];
bool flag;
void Addedge(ll x,ll y)
{
End[++cnt]=y;
Next[cnt]=Last[x],Last[x]=cnt;
}
void DFS(ll x)
{
fa[x]=tot;
for(ll i=Last[x];i;i=Next[i])
if(fa[End[i]]<0) DFS(End[i]);
}
ll Gauss(ll n)
{
ll temp=1,mark=0;
for(ll i=1;i<=n;i++)
{
for(ll j=i+1;j<=n;j++)
while(G[j][i])
{
ll t=G[i][i]/G[j][i];
for(ll k=i;k<=n;k++) G[i][k]=(G[i][k]-t*G[j][k]%mod+mod)%mod;
swap(G[i],G[j]),mark^=1;
}
temp=temp*G[i][i]%mod;
}
if(mark) temp=mod-temp;
return (temp%mod+mod)%mod;
}
int main()
{
scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld",&n,&m),tot=cnt=flag=0;
memset(Last,0,sizeof(Last));
memset(fa,-1,sizeof(fa));
memset(id,0,sizeof(id));
for(ll i=1;i<=n;i++) scanf("%s",s[i]+1);
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++) id[i][j]=(i-1)*m+j;
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
if(s[i][j]!='.')
{
ll tx=i,ty=j;
if(s[i][j]=='U') tx--;
else if(s[i][j]=='D') tx++;
else if(s[i][j]=='L') ty--;
else ty++;
Addedge(id[tx][ty],id[i][j]);
}
DFS(0);
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
if(s[i][j]=='.') tot++,DFS(id[i][j]);
for(ll i=1;i<=n&&!flag;i++)
for(ll j=1;j<=m&&!flag;j++)
if(fa[id[i][j]]<0) flag=true;
if(flag){puts("0");continue;}
if(!tot){puts("1");continue;}
memset(G,0,sizeof(G));
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
if(s[i][j]=='.')
{
ll f=fa[id[i][j]];
if(fa[id[i-1][j]]!=f) G[f][f]++,G[f][fa[id[i-1][j]]]--;
if(fa[id[i][j-1]]!=f) G[f][f]++,G[f][fa[id[i][j-1]]]--;
if(fa[id[i+1][j]]!=f) G[f][f]++,G[f][fa[id[i+1][j]]]--;
if(fa[id[i][j+1]]!=f) G[f][f]++,G[f][fa[id[i][j+1]]]--;
}
printf("%lld\n",Gauss(tot));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: