ACdream 1192 双联通

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <stack>
#define pb push_back
#define pu push
#define mp make_pair
#define eps 1e-9
#define zero(x) (fabs(x)<eps)
#define pi acos(-1.0)
#define f1 first
#define f2 second
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define initial 1,n,1
const int inf=0x3f3f3f3f;
const long long INF=1LL<<50;
using namespace std;
typedef long long LL;
typedef pair <int, int> PII;
template<typename X> inline bool minimize(X&p,X q){if(p<=q)return 0;p=q;return 1;}
template<typename X> inline bool maximize(X&p,X q){if(p>=q)return 0;p=q;return 1;}
queue<int > q1,q2;
#define TT 105
int dx[6]={1,1,0,0,-1,-1};
int dy[6]={-1,0,1,-1,0,1};
int a[TT][TT];
bool vis[TT][TT];
int id[TT][TT];
int n,S,T,idid;
#define M 200000
#define N 11000
int dfs[N],low[N],bccno[N];//3个数组均memset为0
int tim,bcc;
struct edge{
    int u,v;
    edge(int x=0,int y=0):u(x),v(y){}
}e[M];
vector<int > BCC[N],g[N];
bool iscut[N];//初始化为0
stack<edge> SS;
void add(int x,int y)
{
    g[x].pb(y);
    g[y].pb(x);
}
int tarjandfs(int u,int from=-1)
{   int lowu=dfs[u]=++tim;
    int child=0;

    for (int i=0;i<g[u].size();i++)
        {   int v=g[u][i];
            edge e=edge(u,v);
            if (!dfs[v])
                {
                    SS.push(e);
                    child++;
                    int lowv=tarjandfs(v,u);
                    lowu=min(lowu,lowv);
                    if (lowv>=dfs[u])
                        {   iscut[u]=1;
                            bcc++; BCC[bcc].clear();
                            while (1)
                                {
                                    edge x=SS.top(); SS.pop();
                                    if (bccno[x.u]!=bcc) {BCC[bcc].pb(x.u);bccno[x.u]=bcc;}
                                    if (bccno[x.v]!=bcc) {BCC[bcc].pb(x.v);bccno[x.v]=bcc;}
                                    if (x.u==u&&x.v==v) break;
                                }

                        }
                }
            else if (dfs[v]<dfs[u]&&v!=from){
                SS.push(e);
                lowu=min(lowu,dfs[v]);
            }
        }

    if (from<0&&child==1) iscut[u]=0;
    return lowu;
}
char str[TT];
void doit()
{
    scanf("%d",&n);
    memset(a,255,sizeof(a));
    int rr=0,bb=0;
    for (int i=1;i<=n;i++)
    {scanf("%s",str);
    for (int j=1;j<=n;j++)
        {

            if (str[j-1]=='R') {a[i][j]=2;rr++;}
            if (str[j-1]=='B') {a[i][j]=1;bb++;}
            if (str[j-1]=='.') a[i][j]=0;
        }
    }
    if (abs(rr-bb)>=2) {printf("Impossible\n");return;}
    int f1=0,f2=0;
    int nnx,nny,nx,ny;
    memset(vis,0,sizeof(vis));
    for (int i=1;i<=n;i++)if (a[1][i]==2){q1.pu(1),q2.pu(i);vis[1][i]=1;}

    while (!q1.empty())
        {   nx=q1.front(),ny=q2.front();
            q1.pop(); q2.pop();
            for (int dir=0;dir<6;dir++)
                {
                    nnx=nx+dx[dir];
                    nny=ny+dy[dir];
                    if (a[nnx][nny]!=2)continue;
                    if (!vis[nnx][nny])
                        {
                            vis[nnx][nny]=1;
                            q1.pu(nnx);
                            q2.pu(nny);
                        }
                }
        }
    for (int i=1;i<=n;i++)if (vis[n][i]) f1=1;

    memset(vis,0,sizeof(vis));
    for (int i=1;i<=n;i++)if (a[i][1]==1){q1.pu(i),q2.pu(1);vis[i][1]=1;}

    while (!q1.empty())
        {   nx=q1.front(),ny=q2.front();
            q1.pop(); q2.pop();
            for (int dir=0;dir<6;dir++)
                {
                    nnx=nx+dx[dir];
                    nny=ny+dy[dir];
                    if (a[nnx][nny]!=1)continue;
                    if (!vis[nnx][nny])
                        {
                            vis[nnx][nny]=1;
                            q1.pu(nnx);
                            q2.pu(nny);
                        }
                }
        }
    for (int i=1;i<=n;i++)if (vis[i][n]) f2=1;
    if (!f1&&!f2) {printf("Nobody wins\n");return;}
    if (f1&&bb>rr)  {printf("Impossible\n");return;}
    if (f2&&rr>bb)  {printf("Impossible\n");return;}

    idid=0;memset(id,255,sizeof(id));

    if (f1)
        {
            for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
                if (a[i][j]==2) id[i][j]=idid++; S=idid++;T=idid++;
            for (int i=0;i<idid;i++) g[i].clear();
            for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++) if (a[i][j]==2)
            for (int dir=0;dir<3;dir++)
                {
                    if (a[i+dx[dir]][j+dy[dir]]!=2)continue;
                    add(id[i][j],id[i+dx[dir]][j+dy[dir]]);
                }

            for (int i=1;i<=n;i++)if (a[1][i]==2) add(S,id[1][i]);
            for (int i=1;i<=n;i++)if (a[n][i]==2) add(T,id[n][i]);
        }
    if (f2)
        {
            for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
                if (a[i][j]==1) id[i][j]=idid++; S=idid++;T=idid++;
            for (int i=0;i<idid;i++) g[i].clear();
            for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++) if (a[i][j]==1)
            for (int dir=0;dir<3;dir++)
                {
                    if (a[i+dx[dir]][j+dy[dir]]!=1)continue;
                    add(id[i][j],id[i+dx[dir]][j+dy[dir]]);
                }

            for (int i=1;i<=n;i++)if (a[i][1]==1) add(S,id[i][1]);
            for (int i=1;i<=n;i++)if (a[i][n]==1) add(T,id[i][n]);
        }

    bcc=tim=0;
    memset(iscut,0,sizeof(iscut));
    memset(dfs,0,sizeof(dfs));
    memset(low,0,sizeof(low));
    memset(bccno,0,sizeof(bccno));

    tarjandfs(S);
    for (int i=1;i<=bcc;i++)
    {
        int s_e=0,t_e=0;
        for (int j=0;j<BCC[i].size();j++)
            {
                if (BCC[i][j]==S) s_e=1;
                if (BCC[i][j]==T) t_e=1;
            }
        if (s_e&&t_e){printf("Impossible\n");return;}
    }
    if (f1)  {printf("Red wins\n");return;}
    if (f2)  {printf("Blue wins\n");return;}
}
int main()
{   //freopen("rrr.txt","r",stdin);
    while (!SS.empty()) SS.pop();
    int cas,id=0;
    scanf("%d",&cas);
    while (cas--)
        {   printf("Case #%d: ",++id);
            doit();
        }
    return 0;
}
/*
1
7
RR.RBBB
RR.RBBB
RRRRBBB
RR..BBB
RRRRBBB
RR.RBBB
.R.RBBB
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值