来自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. Raid5两块硬盘掉线可以恢复数据吗_raid数据恢复案例分享

    本案例中发生故障的存储类型是HP P2000,虚拟化平台为vmware exsi,共有10块硬盘组成raid5(硬盘容量为1t,其中6号盘是热备盘),由于某些故障导致阵列中两块硬盘亮黄灯掉线,硬盘无法 ...

  2. 微信开发之SVN提交代码与FTP同步到apache的根目录

    SVN是协同开发的,版本控制器,就是几个人同时开发,可以提交代码到SVN服务器,这样就可以协同开发,一般是早上上班首先更新下代码,然后自己修改代码 工作一天之后,修改代码之后,下班之前,更新代码,然后 ...

  3. awk sed tr替换换行符为逗号,并合并为一行

    在群里看到的.记录以备用.  sed 帮助命令:http://man.linuxde.net/sed 文件里有如下行,我想将每行的回车符替换为逗号,并将所有行合并到一行,用awk或sed怎么写啊TOP ...

  4. Java Jar包压缩、解压使用指南

    什么是jar包 JAR(Java Archive)是Java的归档文件,它是一种与平台无关的文件格式,它允许将许多文件组合成一个压缩文件. 如何打/解包 使用jdk/bin/jar.exe工具,配置完 ...

  5. apigw鉴权分析(1-4)新浪微博开放平台 - 鉴权分析

    一.访问入口 http://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E 微博开放接口的调用,如 ...

  6. leetcode算法:Reshape the Matrix

    In MATLAB, there is a very useful function called 'reshape', which can reshape a matrix into a new o ...

  7. 表单中各种input汇总

    html表单 表单用于搜集不同类型的用户输入,表单由不同类型的标签组成,相关标签及属性用法如下: 1.<form>标签 定义整体的表单区域 action属性 定义表单数据提交地址 meth ...

  8. mysql 查询select语句汇总

    数据准备: 创建表: create table students( id int unsigned primary key auto_increment not null, name varchar( ...

  9. HTML中的上下标标签的演示

    HTML中的上下标标签的演示 #table_head>td { font-weight: bold } tr { text-align: center } 作用 标签 演示代码 呈现效果 上标 ...

  10. 翻译:JVM虚拟机规范1.7中的运行时常量池部分(一)

    原文链接: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4 Java Virtual Machine i ...