【CodePlus 2017 12 月赛】白金元首与独舞
2018-03-31 23:47
429 查看
时间限制 : 2000 MS 空间限制 : 512 MB
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
..
..
8
0
1
192
问题描述
样例输入
53 9
LLRRUDUUU
LLR.UDUUU
LLRRUDUUU
4 4
LLRR
L.LL
RR.R
LLRR
4 3
LRD
LUL
DLU
RDL
1 2
LR
2 2
..
..
样例输出
38
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; }
相关文章推荐
- 【LibreOJ】#6259. 「CodePlus 2017 12 月赛」白金元首与独舞
- 「CodePlus 2017 12 月赛」白金元首与独舞
- [矩阵树定理] LOJ#6259. 「CodePlus 2017 12 月赛」白金元首与独舞
- CodePlus 2017 12 月赛 白金元首与独舞 矩阵树定理求有向图生成树数量
- [LOJ6259][CodePlus 2017 12 月赛]白金元首与独舞-矩阵树定理
- 走进矩阵树定理--「CodePlus 2017 12 月赛」白金元首与独舞
- 「CodePlus 2017 12 月赛」火锅盛宴
- 「CodePlus 2017 12 月赛」火锅盛宴(模拟+树状数组)
- 「CodePlus 2017 12 月赛」可做题2(矩阵快速幂+exgcd+二分)
- 【LibreOJ】#6257. 「CodePlus 2017 12 月赛」可做题2
- [几何 扫描线] LOJ#6260. 「CodePlus 2017 12 月赛」寄蒜几盒
- 洛谷 P4032 「CodePlus 2017 12 月赛」火锅盛宴(splay+堆)
- 【LIbreOJ】#6256. 「CodePlus 2017 12 月赛」可做题1
- 【BZOJ5136】【LOJ6256】【CodePlus 2017 12 月赛】可做题1 & LibreOJ6256
- 【loj6257】「CodePlus 2017 12 月赛」可做题2
- LOJ #6256. 「CodePlus 2017 12 月赛」可做题1
- CodePlus 2017 12 月赛 可做题2 矩阵乘法+exgcd
- [BZOJ5109][LOJ #6252][P4061][CodePlus 2017 11月赛]大吉大利,今晚吃鸡!(最短路+拓扑排序+传递闭包+map+bitset(hash+压位))
- LOJ6301:「CodePlus 2018 3 月赛」白金元首与莫斯科 (类插头DP)
- [贪心]「CodePlus 2017 11 月赛」可做题