• [Noi2016]网格


    来自FallDream的博客,未经允许,请勿转载,谢谢。

     

    跳蚤国王和蛐蛐国王在玩一个游戏。
    他们在一个 n 行 m 列的网格上排兵布阵。其中的 c 个格子中 (0≤c≤nm),每个格子有一只蛐蛐,其余的格子中,每个格子有一只跳蚤。
    我们称占据的格子有公共边的两只跳蚤是相邻的。
    我们称两只跳蚤是连通的,当且仅当这两只跳蚤相邻,或存在另一只跳蚤与这两只跳蚤都连通。
    现在,蛐蛐国王希望,将某些(0 个,1 个或多个)跳蚤替换成蛐蛐,使得在此之后存在至少两只跳蚤不连通。
    例如:我们用图表示一只跳蚤,用图表示一只蛐蛐,那么图 1 描述了一个 n=4,m=4,c=2的情况。
    这种情况下蛐蛐国王可以通过将第 2 行第 2 列,和第 3 行第 3 列的两只跳蚤替换为蛐蛐,从而达成他的希望,如图 2 所示。并且,不存在更优的方案,但是可能存在其他替换 2 只跳蚤的方案。
    你需要首先判断蛐蛐国王的希望能否被达成。如果能够达成,你还需要最小化被替换的跳蚤的个数。

    T<=20 1≤n,m≤10^9,0≤c≤min(nm,10^5) ∑c<=10^5

    2s/1G

    真是很蛋疼

    当跳蚤数量小于2或者正好是一对还粘一起的时候答案是-1

    当跳蚤本身不联通的时候答案是0

    当存在一个点把图割开的时候是1

    不然就是2

    好像很简单 乱写了一通之后 成功获得了16分 真轻松  然后就去看了看题解

    只保留在蛐蛐周围的5*5的格子内的跳蚤,四联通建图 建出的图等价 割点可以tarjan求出

    然后如果有跳蚤不联通 那么会有一个蛐蛐的八联通块周围有两个不同的跳蚤联通块

    感觉自己的码力不是很行啊  乱写一通 就这么丑了(吐血)

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #define ll long long
    #define MN 100000
    #define mod 2333333
    using namespace std;
    inline int read()
    {
        int x = 0; char ch = getchar();
        while(ch < '0' || ch > '9') ch = getchar();
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x;
    }
    int n,m,c,top,dn,ans,bel[MN*25+5],Cnt=0,Col=0,head[MN*25+5],en,tot,dfn[MN*25+5],low[MN*25+5],col[MN*2+5];
    vector<int> v[MN+5],V[MN+5];
    bool Cut[MN*25+5],b[MN+5];
    struct P
    {
        int x,y;
        P(int x=0,int y=0):x(x),y(y){}
        P operator+(P b){return P(x+b.x,y+b.y);}
    }p[MN+5],Q[5],q[MN*25+5];
    struct edge{int to,next;}e[MN*100+5];
    struct My_Map
    {
        int Head[mod+5],cnt;
        struct Hash{ll ha;int x,next;}s[25*MN+5];
        void clear()
        {
            cnt=0;
            memset(Head,0,sizeof(Head));
        }
        void ins(int X,int Y)
        {
            ll Ha=1LL*X*m+Y;int j=Ha%mod;
            s[++cnt]=(Hash){Ha,++Cnt,Head[j]};
            Head[j]=cnt;
        }
        int Check(int X,int Y)
        {
            ll Ha=1LL*X*m+Y;int j=Ha%mod;
            for(int i=Head[j];i;i=s[i].next)
                if(s[i].ha==Ha) return s[i].x;
            return 0;
        }
    }mp;
    inline void ins(int f,int t){e[++en]=(edge){t,head[f]};head[f]=en;}
    inline int abs(int x){return x<0?-x:x;}
    bool Check()
    {
        if(1LL*n*m-c>2) return false;
        if(1LL*n*m-c<=1) return true;
        top=0;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m&&top<2;++j)
                if(!mp.Check(i,j)) Q[++top]=P(i,j);
        if(Q[1].x==Q[2].x&&abs(Q[1].y-Q[2].y)==1) return true;
        if(Q[1].y==Q[2].y&&abs(Q[1].x-Q[2].x)==1) return true;
        return false;
    }
    const int dis[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    void build()
    {
        for(int i=1;i<=c;++i)
            for(int j=-2;j<=2;++j)
                for(int k=-2;k<=2;++k)
                    if(j||k)
                    {
                        int x=p[i].x+j,y=p[i].y+k;
                        if(x<=0||y<=0||x>n||y>m||mp.Check(x,y)) continue;
                        mp.ins(x,y);q[Cnt]=P(x,y);
                    }
        for(int i=1,k;i<=Cnt;++i)
            for(int j=0;j<4;++j)
            {
                int x=q[i].x+dis[j][0],y=q[i].y+dis[j][1];
                if(x<=0||y<=0||x>n||y>m||(k=mp.Check(x,y))<=0) continue;
                ins(i,k);
            }
    }
    
    void tj(int x,int fa)
    {
        dfn[x]=low[x]=++dn;bel[x]=tot;Cut[x]=0;int son=0;
        for(int i=head[x];i;i=e[i].next)if(e[i].to!=fa)
        {
            if(!dfn[e[i].to])
            {
                ++son,tj(e[i].to,x),low[x]=min(low[x],low[e[i].to]);
                if(low[e[i].to]>=dfn[x]) Cut[x]=1;
            }
            else low[x]=min(low[x],dfn[e[i].to]);
        }
        if(son==1&&!fa) Cut[x]=0;
    }
    
    bool Round(int id)
    {
        for(int i=-1;i<=1;++i)
            for(int j=-1;j<=1;++j)
                if(i||j)
                {
                    int x=q[id].x+i,y=q[id].y+j;
                    if(x&&y&&mp.Check(x,y)<0)return 1;
                }
        return 0;
    }
    
    bool check(int t)
    {
        int col=-1;
        for(int l=0;l<V[t].size();++l)
        {
            int X=p[V[t][l]].x,Y=p[V[t][l]].y;
            for(int i=-2;i<=2;++i)
                for(int j=-2,k;j<=2;++j)
                    if(i||j)
                    {
                        int x=X+i,y=Y+j;
                        if(x<1||y<1||x>n||y>m||(k=mp.Check(x,y))<0) continue;
                        if(col==-1) col=bel[k];
                        else if(col!=bel[k]) return true;
                    }
        }
        return false;
    }
    
    void Dfs(int x)
    {
        col[x]=Col;V[Col].push_back(x);
        for(int j=0;j<v[x].size();++j)
            if(!col[v[x][j]]) Dfs(v[x][j]);
    }
    
    int main()
    {
        for(int T=read();T;--T)
        {
            n=read();m=read();c=read();ans=2;mp.clear();
            if(m==1||n==1) ans=1;Cnt=-c-1;
            for(int i=1;i<=c;++i)
                p[i].x=read(),p[i].y=read(),mp.ins(p[i].x,p[i].y);
            if(Check()) puts("-1");
            else
            {
                Cnt=0;en=0;tot=0;dn=0;Col=0;build();
                for(int i=1,k;i<=c;++i)
                    for(int j=0;j<4;++j)
                    {
                        int x=p[i].x+dis[j][0],y=p[i].y+dis[j][1];
                        if(x<1||y<1||x>n||y>m) continue;
                        if((k=mp.Check(x,y))<0) v[i].push_back(k+c+1);
                    }
                for(int i=1;i<=c;++i)
                    if(!col[i]) ++Col,Dfs(i);
                for(int i=1;i<=Cnt;++i)
                    if(!dfn[i]) ++tot,tj(i,0);
                for(int i=1;i<=Cnt&&ans>1;++i) if(Cut[i]&&Round(i)) ans=1;
                for(int i=1;i<=Col&&ans;++i)
                    if(check(i)) ans=0;
                printf("%d
    ",ans);
                memset(head,0,sizeof(int)*(Cnt+5));
                for(int i=1;i<=c;++i) v[i].clear(),V[i].clear();
                memset(dfn,0,sizeof(int)*(Cnt+5));
                memset(low,0,sizeof(int)*(Cnt+5));
                memset(col,0,sizeof(int)*(c+5));
            }
        }
        return 0;
    }
  • 相关阅读:
    docker入门
    spring aop切面入门
    java 拉姆达 lamdba get
    Spring 3
    Spring 进阶二
    腾讯云 视频 点播 视频上传接口
    js 实时获取后台数据 Spring
    Spring 进阶一
    hibernate 第四天 重点查询的方式
    hibernate 第三天
  • 原文地址:https://www.cnblogs.com/FallDream/p/Noi2016d1t2.html
Copyright © 2020-2023  润新知