【JZOJ3809】设备塔

Description

为了封印辉之环,古代塞姆利亚大陆的人民在异空间中建造了一座设备塔。
简单的说,这座设备塔是一个漂浮在异空间中的圆柱体,圆柱体两头的圆是计算核心,而侧面则是传输信息所用的数据通道,划分成N *m 个区块。
然而,随着工作的继续进行,他们希望把侧面的一部分区块也改造成其他模块。然而,任何时候都必须保证存在一条数据通道,能从圆柱体的一端通向另一端。
由于无法使用辉之环掌控下的计算系统,他们寻求你的帮助来解决这个问题。他们将逐个输入想要改造的区域,而你则执行所有可行的改造并忽略可能导致数据中断的改造。

Solution

因为是环,所以复制一份。

然后每个点向四周非空的方块连边,那么判断不合法就是判断该点和复制后的点是否联通。

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 3010
using namespace std;
int fx[8][2]={{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1}};
int n,m;
int f[N*N*2];
bool bz[N][N*2];
int g(int x,int y){
    return (x-1)*m*2+y;
}
int find(int x){
    return !f[x]?x:f[x]=find(f[x]);
}
int main()
{
    int t;
    scanf("%d %d %d",&n,&m,&t);
    int ans=0;
    while(t--)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        if(!y) y=m;
        bool tf=false;
        fo(i,0,7)
        {
            int x1=x+fx[i][0],y1=(y+fx[i][1])%(m*2);
            if(!y1) y1=m*2;
            if(x1<1 || x1>n) continue;
            if(!bz[x1][y1]) continue;
            fo(j,0,7)
            {
                int x2=x+fx[j][0],y2=(y+m+fx[j][1])%(m*2);
                if(!y2) y2=m*2;
                if(x2<1 || x2>n) continue;
                if(!bz[x2][y2]) continue;
                int t1=find(g(x1,y1)),t2=find(g(x2,y2));
                if(t1==t2)
                {
                    tf=true;
                    break;
                }
            }
            if(tf) break;
        }
        if(!tf)
        {
            ans++;
            fo(i,0,7)
            {
                int t;
                int x1=x+fx[i][0],y1=(y+fx[i][1])%(m*2);
                if(!y1) y1=m*2;
                if(x1<1 || x1>n) continue;
                if(!bz[x1][y1]) continue;
                int t1=find(g(x1,y1));
                t=find(g(x,y));
                if(t1!=t) f[t1]=t;
            }
            fo(i,0,7)
            {
                int t;
                int x2=x+fx[i][0],y2=(y+m+fx[i][1])%(m*2);
                if(!y2) y2=m*2;
                if(x2<1 || x2>n) continue;
                if(!bz[x2][y2]) continue;
                int t2=find(g(x2,y2));
                t=find(g(x,y+m));
                if(t2!=t) f[t2]=t;
            }
            bz[x][y]=bz[x][y+m]=1;
        }
    }
    printf("%d",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值