列表

详情


NC216007. Go

描述

Go is an adversarial game with the objective of surrounding a larger total area of the board with one's stones than the opponent's. The core idea of the game is the concept of liberty, which is an open point, or rather, an intersection of vertical and horizontal lines on the chessboard with no stones on it, bordering the group.

A stone, white or black, is called alive if it has at least one liberty directly orthogonally adjacent (up, down, left, or right), or must be in the same connected group with a stone of the same color which is alive. We say two stones of the same color are directly connected if they're orthogonally adjacent. We say two stones s_1 and s_k of the same color are in the same connected group if there exists a sequence of stones such that for all , and s_i are of the same color and are directly connected.

For example, in the left part of the below figure, neither of the two white stones is alive, as they're captured by the surrounding black stones; While in the right part, the rightmost white stone is also not alive, even if the leftmost black stone is also not alive.



Given a chessboard with n vertical and n horizontal lines where some stones might be lying on, please calculate the number of white stones captured by the black ones (that is to say, calcaulate the number of white stones not alive). The results for the above examples are 2 and 1, respectively.

However, our dear friend Kotori thinks that this problem is too simple for our clever contestants to solve, so she would like to heat things up by instead asking you to flip the color of each stone (that is to say, change a black stone to a white one, or vice versa2) independently and find out the corresponding answer after each flip.

By flipping independently we mean that before flipping the color of a stone, the other stones should change back to their original color. Also note that the data in this problem is not from the real world, which means that the size of the chessboard is not necesssarily , and the number of white and black stones can be any integer.
                                    
2Vice versa: The reverse is also true. Here it can be replaced with "change a white stone to a black one". This is a very common phrase in modern English especially in academic writing, so please bear it in mind.

输入描述

There are multiple test cases. The first line of the input contains an integer T indicating the number of test cases. For each test case:

The first line contains one integer n () indicating the length of the board side.

For the next n lines, the i-th line contains a string ( , , ), where indicates that the intersection on the i-th row and the j-th column contains a black stone. Similarly for a white stone and for an empty intersection.

It's guaranteed that the sum of n over all test cases does not exceed .

输出描述

For each test case output an integer E modulo which is the answer encoded as follows:

1. Sort all the stones with their row number (from top to bottom) as the primary sort key and their column number (from left to right) as the secondary sort key;

2. , where m is the number of stones and a_i is the number of white stones not alive after flipping the color of the i-th stone.

NOTE that the MODULUS and the BASE are DIFFERENT.

示例1

输入:

3
2
.o
..
3
.x.
xoo
ox.
2
oo
oo

输出:

0
870527216
485539347

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++11) 解法, 执行用时: 1852ms, 内存消耗: 229700K, 提交时间: 2021-02-04 16:17:19

#include <bits/stdc++.h>
#define rep0(i,r) for (int i=0,i##end=r;i<i##end;++i)
#define rep(i,l,r) for (int i=l;i<=r;++i)
#define per(i,r,l) for (int i=r;i>=l;--i)
#define ll long long
using namespace std;
const int V=2e6+6,B=1e6+7,P=1e9+7,dx[]={-1,0,1,0},dy[]={0,-1,0,1};
int n,a[V],c[V],sz[V],gas[V],rt[V],fa[V];
vector<int> G[V],T[V];
int dfn[V],dc,low[V],st[V],tp,nc;
void Tarjan(int u){
	dfn[u]=low[u]=++dc,st[++tp]=u;
	rep0(i,G[u].size()){
		int v=G[u][i];
		if (!dfn[v]){
			Tarjan(v),low[u]=min(low[u],low[v]);
			if (low[v]==dfn[u]){
				++nc;
				for (int x=0;x!=v;--tp){
					x=st[tp],T[nc].push_back(x),T[x].push_back(nc);
				}
				T[nc].push_back(u),T[u].push_back(nc);
			}
		}
		else low[u]=min(low[u],dfn[v]);
	}
}
void dfs(int u,int f){
	sz[u]=u<=n*n&&a[u]==1,gas[u]=c[u],rt[u]=!f?u:rt[f],fa[u]=f;
	rep0(i,T[u].size()){
		int v=T[u][i]; if (v!=f) dfs(v,u),sz[u]+=sz[v],gas[u]+=gas[v];
	}
}
int ID(int x,int y){ return (x-1)*n+y; }
bool in(int x,int y){ return 1<=x&&x<=n&&1<=y&&y<=n; }
void adde(int u,int v){ G[u].push_back(v),G[v].push_back(u); }
int main(){
	int cas; scanf("%d",&cas);
	while (cas--){
		scanf("%d",&n);
		rep(i,1,2*n*n) a[i]=c[i]=dfn[i]=rt[i]=0,T[i].clear(),G[i].clear();
		rep(i,1,n){
			static char s[2000]; scanf("%s",s);
			rep(j,1,n){
				int u=ID(i,j);
				if (s[j-1]=='x') a[u]=2;
				else if (s[j-1]=='o') a[u]=1;
				else a[u]=-1;
			}
		}
		rep(i,1,n)
			rep(j,1,n){
				int u=ID(i,j);
				if (i<n&&a[u]==1&&a[ID(i+1,j)]==1) adde(u,ID(i+1,j));
				if (j<n&&a[u]==1&&a[ID(i,j+1)]==1) adde(u,ID(i,j+1));
				rep(w,0,3) 
					if (in(i+dx[w],j+dy[w])) c[u]+=a[ID(i+dx[w],j+dy[w])]==-1;
			}
		int cnt=0; nc=n*n,dc=tp=0;
		rep(i,1,n) rep(j,1,n){
			int u=ID(i,j); if (!dfn[u]) Tarjan(u),dfs(u,0),cnt+=!gas[u]?sz[u]:0;
		}
		int ans=0;
		rep(i,1,n)
			rep(j,1,n)
				if (a[ID(i,j)]==1){
					int u=ID(i,j),d=!gas[rt[u]]?-sz[rt[u]]:0;
					rep0(k,T[u].size()){
						int v=T[u][k];
						if (v!=fa[u]) d+=!gas[v]?sz[v]:0;
						else d+=gas[rt[u]]-gas[u]==0?sz[rt[u]]-sz[u]:0;
					}
					ans=((ll)ans*B+cnt+d)%P;
				}
				else if (a[ID(i,j)]==2){
					int d=0,g=c[ID(i,j)],s=1;
					rep(w,0,3){
						int x=i+dx[w],y=j+dy[w];
						if (in(x,y)&&a[ID(x,y)]==1){
							int u=rt[ID(x,y)]; bool t=false; 
							rep(w0,0,w-1) 
								if (in(i+dx[w0],j+dy[w0])&&rt[ID(i+dx[w0],j+dy[w0])]==u){ t=true; break; }
							if (t) continue;
							if (!gas[u]) d-=sz[u]; g+=gas[u],s+=sz[u];
						}
					} 
					if (!g) d+=s; ans=((ll)ans*B+cnt+d)%P;
				}
		printf("%d\n",ans);
	}
	return 0;
}

上一题