来自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 = ; char ch = getchar();
while(ch < '' || ch > '') ch = getchar();
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x;
}
int n,m,c,top,dn,ans,bel[MN*+],Cnt=,Col=,head[MN*+],en,tot,dfn[MN*+],low[MN*+],col[MN*+];
vector<int> v[MN+],V[MN+];
bool Cut[MN*+],b[MN+];
struct P
{
int x,y;
P(int x=,int y=):x(x),y(y){}
P operator+(P b){return P(x+b.x,y+b.y);}
}p[MN+],Q[],q[MN*+];
struct edge{int to,next;}e[MN*+];
struct My_Map
{
int Head[mod+],cnt;
struct Hash{ll ha;int x,next;}s[*MN+];
void clear()
{
cnt=;
memset(Head,,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 ;
}
}mp;
inline void ins(int f,int t){e[++en]=(edge){t,head[f]};head[f]=en;}
inline int abs(int x){return x<?-x:x;}
bool Check()
{
if(1LL*n*m-c>) return false;
if(1LL*n*m-c<=) return true;
top=;
for(int i=;i<=n;++i)
for(int j=;j<=m&&top<;++j)
if(!mp.Check(i,j)) Q[++top]=P(i,j);
if(Q[].x==Q[].x&&abs(Q[].y-Q[].y)==) return true;
if(Q[].y==Q[].y&&abs(Q[].x-Q[].x)==) return true;
return false;
}
const int dis[][]={{,},{-,},{,},{,-}};
void build()
{
for(int i=;i<=c;++i)
for(int j=-;j<=;++j)
for(int k=-;k<=;++k)
if(j||k)
{
int x=p[i].x+j,y=p[i].y+k;
if(x<=||y<=||x>n||y>m||mp.Check(x,y)) continue;
mp.ins(x,y);q[Cnt]=P(x,y);
}
for(int i=,k;i<=Cnt;++i)
for(int j=;j<;++j)
{
int x=q[i].x+dis[j][],y=q[i].y+dis[j][];
if(x<=||y<=||x>n||y>m||(k=mp.Check(x,y))<=) continue;
ins(i,k);
}
} void tj(int x,int fa)
{
dfn[x]=low[x]=++dn;bel[x]=tot;Cut[x]=;int son=;
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]=;
}
else low[x]=min(low[x],dfn[e[i].to]);
}
if(son==&&!fa) Cut[x]=;
} bool Round(int id)
{
for(int i=-;i<=;++i)
for(int j=-;j<=;++j)
if(i||j)
{
int x=q[id].x+i,y=q[id].y+j;
if(x&&y&&mp.Check(x,y)<)return ;
}
return ;
} bool check(int t)
{
int col=-;
for(int l=;l<V[t].size();++l)
{
int X=p[V[t][l]].x,Y=p[V[t][l]].y;
for(int i=-;i<=;++i)
for(int j=-,k;j<=;++j)
if(i||j)
{
int x=X+i,y=Y+j;
if(x<||y<||x>n||y>m||(k=mp.Check(x,y))<) continue;
if(col==-) 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=;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=;mp.clear();
if(m==||n==) ans=;Cnt=-c-;
for(int i=;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=;en=;tot=;dn=;Col=;build();
for(int i=,k;i<=c;++i)
for(int j=;j<;++j)
{
int x=p[i].x+dis[j][],y=p[i].y+dis[j][];
if(x<||y<||x>n||y>m) continue;
if((k=mp.Check(x,y))<) v[i].push_back(k+c+);
}
for(int i=;i<=c;++i)
if(!col[i]) ++Col,Dfs(i);
for(int i=;i<=Cnt;++i)
if(!dfn[i]) ++tot,tj(i,);
for(int i=;i<=Cnt&&ans>;++i) if(Cut[i]&&Round(i)) ans=;
for(int i=;i<=Col&&ans;++i)
if(check(i)) ans=;
printf("%d\n",ans);
memset(head,,sizeof(int)*(Cnt+));
for(int i=;i<=c;++i) v[i].clear(),V[i].clear();
memset(dfn,,sizeof(int)*(Cnt+));
memset(low,,sizeof(int)*(Cnt+));
memset(col,,sizeof(int)*(c+));
}
}
return ;
}

[Noi2016]网格的更多相关文章

  1. [UOJ#220][BZOJ4651][Noi2016]网格

    [UOJ#220][BZOJ4651][Noi2016]网格 试题描述 跳蚤国王和蛐蛐国王在玩一个游戏. 他们在一个 n 行 m 列的网格上排兵布阵.其中的 c 个格子中 (0≤c≤nm),每个格子有 ...

  2. 洛谷P1173 [NOI2016]网格

    这个码量绝对是业界大毒瘤...... 300行,6.5k,烦的要死...... 题意:给你一个网格图,里面有0或1.你需要把一些0换成1使得存在某两个0不四联通.输出最小的换的数量.无解-1. n,m ...

  3. [BZOJ4651][NOI2016]网格(Tarjan)

    下面直接给出结论,相关证明见官方题解. 1.若跳蚤数不超过1或仅有两只跳蚤且相邻,则答案为-1. 2.若跳蚤形成的连通块个数大于1,则答案为0. 3.若跳蚤之间建图存在割点,则答案为1. 4.否则为2 ...

  4. BZOJ4651 & 洛谷1173 & UOJ220:[NOI2016]网格——题解(附debug数据)

    https://www.lydsy.com/JudgeOnline/problem.php?id=4651 https://www.luogu.org/problemnew/show/P1173#su ...

  5. BZOJ4651/UOJ220 [Noi2016]网格

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  6. 并不对劲的bzoj4651:loj2084:uoj220:p1173:[NOI2016]网格

    题目大意 有一个\(n*m\)(\(n,m\leq10^9\))的网格,每个格子是空地或障碍(\(障碍数\leq10^5\)) 定义两块空地连通,当且仅当它们是"相邻的两块空地"或 ...

  7. BZOJ4651 NOI2016网格(割点)

    首先显然可以通过孤立角落里的跳蚤使其不连通,所以只要有解答案就不会大于2.同样显然的一点是当且仅当跳蚤数量<=2且连通时无解.做法其实也很显然了:特判无解,若跳蚤不连通输出0,否则看图中是否无割 ...

  8. UOJ220 [NOI2016] 网格 【割顶】【并查集】

    题目分析: 答案显然只有{-1,0,1,2}四种. 对于答案等于-1的情况,只有两种情况,一种是只剩一只跳蚤,另一种是只剩两只跳蚤且他们四连通,这个很好判. 对于答案等于0的情况,那说明联通块大于1, ...

  9. NOI2016

    luoguP1712 [NOI2016]区间 这是一道送分题. 对于我这种每天抄题解不动脑子思维僵化得厉害的智障选手就是送命题. 一直在想端点排序各种Treap搞... 正解: 已知一些区间,如何判断 ...

随机推荐

  1. Welcome to Django!

    Welcome to Django! 实验简介 Django是一个可以使Web开发工作更加高效愉快的Web开发框架.Django可以让你用最小的代价构建和维护更高质量的Web应用程序. 从好的方面来看 ...

  2. vmware ubuntu蓝屏

    ctrl+alt+f4 sudo apt-get update sudo apt-get upgrade sudo apt-get install xserver-xorg-lts-utopic su ...

  3. 【iOS】Swift LAZY 修饰符和 LAZY 方法

    延时加载或者说延时初始化是很常用的优化方法,在构建和生成新的对象的时候,内存分配会在运行时耗费不少时间,如果有一些对象的属性和内容非常复杂的话,这个时间更是不可忽略.另外,有些情况下我们并不会立即用到 ...

  4. xapp1151_Param_CAM模块安装

    xapp1151_Param_CAM模块安装 所需生成模块 TCAM CAM 下载链接 赛灵思技术支持网站:http://www.xilinx.com/support.html 并在网页中搜索xapp ...

  5. Flask 视图

    写个验证用户登录的装饰器:在调用函数前,先检查session里有没有用户 from functools import wraps from flask import session, abort de ...

  6. Codechef March Challenge 2014——The Street

    The Street Problem Code: STREETTA https://www.codechef.com/problems/STREETTA Submit Tweet All submis ...

  7. JAVA_SE基础——1.JDK&JRE下载及安装

    这是我学了JAVA来写的第一篇博客: 我首先是在传智播客领了张.毕向东老师的免费JAVA学习光盘来学习! 下面我来教大家安装使用JAVA时候必备的JDK 1.首先上甲骨文公司的官方网站下载JDK的安装 ...

  8. 关于python爬虫经常要用到的一些Re.正则表达式

    转载:https://blog.csdn.net/skyeyesxy/article/details/50837984 1.正则表达式的常用符号与方法 常用符号:点号,星号,问号与括号(小括号) (. ...

  9. 原生JS封装时间运动函数

    /*讲时间运动之前先给大家复习一下运动函数 通常大家都会写运动框架,一个定时器(Timer),一个步长(step 就是每次运动的距离),一个当前位置(current)一个目标位置(target),然后 ...

  10. Android自定义圆形图片工具类(CTRL+C加CTRL+V直接使用)

    先贴一下工具类的代码!可直接复制粘贴 public class RoundImageView extends ImageView { private Paint mPaint; //画笔 privat ...