题目分析:

答案显然只有{-1,0,1,2}四种。

对于答案等于-1的情况,只有两种情况,一种是只剩一只跳蚤,另一种是只剩两只跳蚤且他们四连通,这个很好判。

对于答案等于0的情况,那说明联通块大于1,把图离散出来连边并查集判就可以了。

对于答案等于1的情况,我们要考虑唯一的联通块是否存在割顶,具体的,我们发现答案只可能是有蛐蛐的格子旁边的八个格子(n=1或m=1除外),那么把它们提取出来单独建点,而其它的离散,跑一边割顶就可以做了。

剩下的输出2.

代码:

 #include<bits/stdc++.h>
using namespace std; const int maxn = ; int n,m,c,tot;
pair<int,int> pr[maxn];
vector<pair<int,int> > vec[maxn];
int arr[maxn],mlgb[maxn],isg[maxn];
vector<int> g[maxn];
int dx[]={,,,-,,-,,-};
int dy[]={,-,,,,-,-,};
int chk,pre[maxn];
int low[maxn],dfn[maxn],cl,fa[maxn]; void init(){
memset(pr,,sizeof(pr));
for(int i=;i<=tot;i++) low[i]=dfn[i]=fa[i]=isg[i]=arr[i]=;
for(int i=;i<=tot;i++) vec[i].clear(),g[i].clear();
cl = chk = n = m = c = tot = ;
} int found(int x){
int rx = x; while(pre[rx] != rx) rx = pre[rx];
while(pre[x] != rx){int tmp = pre[x]; pre[x] = rx; x = tmp;}
return rx;
} int pd0(){
sort(pr+,pr+c+);pr[] = make_pair(,m+);
int tnum = ,pnum = ;
int zt = ;
for(int i=;i<=c;i++) arr[++zt]=pr[i].first-,arr[++zt]=pr[i].first+,arr[++zt]=pr[i].first;
sort(arr+,arr+zt+); zt = unique(arr+,arr+zt+)-arr-;
while(arr[zt] == n+)zt--;
for(int i=;i<=zt;i++){
if(arr[i] == ) continue;
if(arr[i] != arr[i-]+){vec[++tnum].push_back(make_pair(,m));tot++;}
tnum++;
int lst = lower_bound(pr+,pr+c+,make_pair(arr[i]-,))-pr;
int now = lower_bound(pr+,pr+c+,make_pair(arr[i],))-pr;
if(pr[now].first != arr[i]) now = ;
int imp=;while(lst<=c&&pr[lst].first<=arr[i]+) mlgb[++imp]=pr[lst].second,lst++;
sort(mlgb+,mlgb+imp+); imp = unique(mlgb+,mlgb+imp+)-mlgb-;
int z = ;int j = now,k = ;
while(z <= m){
if(k > imp){vec[tnum].push_back(make_pair(z,m));tot++;z=m+;break;}
while(pr[j].first==arr[i]&&pr[j].second<mlgb[k])j++;
if(z < mlgb[k]-){vec[tnum].push_back(make_pair(z,mlgb[k]-));tot++;z = mlgb[k]-;}
if(z < mlgb[k]){isg[++tot]=;vec[tnum].push_back(make_pair(z,mlgb[k]-));z = mlgb[k];}
if(z==mlgb[k]&&(!(pr[j].first==arr[i]&&pr[j].second==mlgb[k]))){
isg[++tot]=;vec[tnum].push_back(make_pair(z,mlgb[k]));z = mlgb[k]+;
}else z = mlgb[k]+;
if(z > m) break;
while(pr[j].first==arr[i]&&pr[j].second<mlgb[k]+)j++;
if(!(pr[j].first==arr[i]&&pr[j].second==mlgb[k]+)){
isg[++tot]=;vec[tnum].push_back(make_pair(z,mlgb[k]+));z = mlgb[k]+;
}
k++;
}
}
if(arr[zt] != n){vec[++tnum].push_back(make_pair(,m));tot++;}
for(int i=;i<tot;i++) pre[i] = i;
for(int i=;i<tnum;i++){
int k = ;
for(int j=;j<vec[i].size();j++){
while(k<vec[i+].size()&&vec[i+][k].second < vec[i][j].first) k++;
while(k<vec[i+].size()&&vec[i+][k].second <= vec[i][j].second){
g[pnum+j].push_back(pnum+vec[i].size()+k);
g[pnum+vec[i].size()+k].push_back(pnum+j);
pre[found(pnum+j)] = found(pnum+vec[i].size()+k); k++;
}
if(k<vec[i+].size()&&vec[i+][k].first <= vec[i][j].second){
g[pnum+j].push_back(pnum+vec[i].size()+k);
g[pnum+vec[i].size()+k].push_back(pnum+j);
pre[found(pnum+j)] = found(pnum+vec[i].size()+k);
}
}
pnum += vec[i].size();
}
pnum = ;
for(int i=;i<=tnum;i++){
for(int j=;j<vec[i].size();j++){
if(vec[i][j].first == vec[i][j-].second+){
g[pnum+j].push_back(pnum+j-);
g[pnum+j-].push_back(pnum+j);
pre[found(pnum+j)] = found(pnum+j-);
}
}
pnum += vec[i].size();
}
int hh = ;
for(int i=;i<tot;i++){if(pre[i] == i) hh++;}
if(hh>) return ; else return ;
} void Tarjan(int now){
low[now] = dfn[now] = ++cl;
for(int i=;i<g[now].size();i++){
if(g[now][i] == fa[now]) continue;
if(dfn[g[now][i]] > dfn[now]) continue;
if(dfn[g[now][i]] == ){
fa[g[now][i]] = now;Tarjan(g[now][i]);
low[now] = min(low[now],low[g[now][i]]);
}else{low[now] = min(low[now],dfn[g[now][i]]);}
}
if(isg[now+]==)return;
if(now != ){
for(int i=;i<g[now].size();i++){
if(fa[g[now][i]] != now) continue;
if(low[g[now][i]] >= dfn[now]){chk=;}
}
}else{
int nh = ;
for(int i=;i<g[now].size();i++){if(fa[g[now][i]] == now){nh++;}}
if(nh > ) chk++;
}
} void read(){
scanf("%d%d%d",&n,&m,&c);
for(int i=;i<=c;i++){scanf("%d%d",&pr[i].first,&pr[i].second);}
} void work(){
if(1ll*n*m-c <= ){puts("-1");return;}
if(1ll*n*m-c == ){
sort(pr+,pr+c+); pair<int,int> l1,l2;
for(int i=;i<=n;i++) for(int j=;j<=m;j++){
int z = lower_bound(pr+,pr+c+,make_pair(i,j))-pr;
if(pr[z] == make_pair(i,j)) continue;
if(l1 != make_pair(,)) l2=make_pair(i,j); else l1=make_pair(i,j);
}
if(abs(l1.first-l2.first)+abs(l1.second-l2.second)==){puts("-1");}
else puts("");
return;
}
if(pd0()) {puts("");return;}
if(n == || m == ){puts("");return;}
Tarjan();
if(chk){puts("");return;}
else puts("");
} int main(){
int Tmp; scanf("%d",&Tmp);
while(Tmp--){
init();
read();
work();
}
return ;
}

UOJ220 [NOI2016] 网格 【割顶】【并查集】的更多相关文章

  1. 【XSY2741】网格 分治 LCT 并查集

    题目描述 有一个\(n\times m\)的网格,线框的交点可以扭动,边不可伸缩.网格中有一些格子里面放了'x'形的支架,这些格子不会变形,但可以整体转动.如果所有格子都不能变形,那么称这个网格稳固. ...

  2. BZOJ4651/UOJ220 [Noi2016]网格

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

  3. HDU 6081 度度熊的王国战略【并查集/数据弱水题/正解最小割算法】

    链接6081 度度熊的王国战略 Time Limit: 40000/20000 MS (Java/Others) Memory Limit: 32768/132768 K (Java/Others) ...

  4. BZOJ4423 AMPPZ2013Bytehattan(并查集)

    判断网格图中某两点是否被割开,可以将割边视为边区域视为点,转化为可切割这两点的区域是否连通.于是每次判断使两个区域连通后是否会形成环(边界视为连通),若是则说明被两点被割开.并查集维护. #inclu ...

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

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

  6. BZOJ_4423_[AMPPZ2013]Bytehattan_对偶图+并查集

    BZOJ_4423_[AMPPZ2013]Bytehattan_对偶图+并查集 Description 比特哈顿镇有n*n个格点,形成了一个网格图.一开始整张图是完整的. 有k次操作,每次会删掉图中的 ...

  7. 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

    图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...

  8. 【BZOJ-4423】Bytehattan 并查集 + 平面图转对偶图

    4423: [AMPPZ2013]Bytehattan Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 144  Solved: 103[Submit][ ...

  9. 并查集 Union-Find

    并查集能做什么? 1.连接两个对象; 2.查询两个对象是否在一个集合中,或者说两个对象是否是连接在一起的. 并查集有什么应用? 1. Percolation问题. 2. 无向图连通子图个数 3. 最近 ...

随机推荐

  1. Centos7修改为固定IP后 yum 出现could not retrieve mirrorlist

    Centos7修改为固定IP后 yum 出现could not retrieve mirrorlist,发现yum源的域名无法解析 按照6,修改/etc/resovle.conf,新增域名解析服务器1 ...

  2. Linux下不借助工具实现远程linux服务器上传下载文件

    # Linux下不借助工具实现远程linux服务器上传下载文件 ## 简介 - Linux下自带ssh工具,可以实现远程Linux服务器的功能- Linux下自带scp工具,可以实现文件传输功能 ## ...

  3. Maven Multi-Module Example

    Maven Multi-Module - 国内版 Binghttps://cn.bing.com/search?q=Maven+Multi-Module&qs=n&form=QBRE& ...

  4. nxp基于layerscape系列芯片的硬件型号解析

    每一种layerscape系列芯片都有两种硬件型号: RDB 和QDS RDB: Refrence Design Board QDS: QorIQ Development system

  5. functools.partial偏函数的使用

    https://docs.python.org/3.6/library/functools.html 从名字可以看出,该函数的作用就是部分使用某个函数,即冻结住某个函数的某些参数,让它们保证为某个值, ...

  6. opencv3.4.6 cmake

    Selecting Windows SDK version to target Windows 10.0.16299. Found PythonInterp: N:/Anaconda3/install ...

  7. Dart中的类型转换总结:

    1.Dart中数组转换为字符串:join var a=[1,2,3,4]; var str=a.join(',');

  8. 泡泡一分钟:SceneCut: Joint Geometric and Object Segmentation for Indoor Scenes

    张宁    SceneCut: Joint Geometric and Object Segmentation for Indoor Scenes    "链接:https://pan.ba ...

  9. 【Tomcat】Tomcat 配置JNDI数据源(三)

    数据源的由来 在Java开发中,使用JDBC操作数据库的四个步骤如下:   ①加载数据库驱动程序(Class.forName("数据库驱动类");)   ②连接数据库(Connec ...

  10. 青葱的岁月 Mybatis JdbcType与Oracle、MySql数据类型对应列表

    Mybatis JdbcType Oracle MySql JdbcType ARRAY     JdbcType BIGINT   BIGINT JdbcType BINARY     JdbcTy ...