思路:
蛋疼的一道题
当时做同步赛的时候这道题爆零了= =
%%%TA爷现场AC
连c=0的情况也没写
用到的算法很简单,离散化+求割点(然而当时的我并不会求割点= =)
但是写起来有很多要注意的细节问题
先说一下总体做法
很容易想到答案就是-1,0,1,2(显然,当时的我就算没学割点也看出来了……)
考虑分开讨论
-1
n∗m−k<=1n*m-k或(n∗m−k=2n*m-k=2且连在一起)
0
n∗m−k>=2n*m-k>=2且至少存在两个联通块
1
只有一个联通块,但有割点
2
除上面三种情况以外
情况看起来也很简单啊
但是实现起来并不容易
因为nn,mm太大所以要离散化建图
怎么建呢?
所有蛐蛐周围一圈的八个点
一开始我想的是建周围两圈,即24个点
然后检查每个跳蚤往其向下和向右碰到的第一个点,如果也是跳蚤就连边(这个可以分别按照x,y的关键字优先级排序来做)
然后dfs一遍,检查是否连通及是否存在割点即可
但如果仅仅这样建图,下面这个样例是无法处理的

5 5 1
3 5

画出来是这样的

如果如上建图,5×55×5的网格就变成了3×33×3的网格,原本不存在割点,而现在又有了
那怎么办呢?
我们可以把这个图再扩大一圈
也就是说检查我们所离散的点是否已经到达网格的边界,如果没有到达,就在他们周围在加一圈
比如上述这个样例错误的离散化是这样的

(因为这样就出来割点了)
正确的离散化

(实际上就是把最小的x,y-1,最大的x,y+1,注意不能超过[1,n],[1,m]的范围)
这样建好图以后就可以跑tarjan求割点了
注意数组范围的大小
每个蝈蝈最多可以扩展出8个点,而且离散后的x,y坐标为11~3×1053×10^5,在周围再扩充一层点的个数是1.2×1061.2×10^6
这样总点数大约是2×1062×10^6个
每个点最多会向外连4条边,所以边数为8×1068×10^6
在UOJ上刷了一页的97pts
代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define M 100005
#define LL long long
using namespace std;
int T,n,m,k,ID,cnt,tot,lef,rit,up,down;
bool any_cut,key;
struct node{int id,x,y;bool operator <(const node other)const{if (key)    if (x==other.x) return y<other.y;else return x<other.x;elseif (y==other.y) return x<other.x;else return y<other.y;}bool operator ==(const node other)const{return x==other.x&&y==other.y;}
}a[M],b[M*25];
int X[M*3],Y[M*3],first[M*25],low[M*25],dfn[M*25];
struct edge{int v,next;
}e[M*90];
int in()
{int t=0;char ch=getchar();while (ch>'9'||ch<'0') ch=getchar();while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-48,ch=getchar();return t;
}
void add(int x,int y)
{e[++tot].v=y;e[tot].next=first[x];first[x]=tot;e[++tot].v=x;e[tot].next=first[y];first[y]=tot;
}
void dfs(int x,int fa)
{dfn[x]=low[x]=++dfn[0];int child=0;for (int i=first[x];i;i=e[i].next)if (e[i].v!=fa)if (!dfn[e[i].v]){child++;dfs(e[i].v,x);low[x]=min(low[x],low[e[i].v]);if (fa&&dfn[x]<=low[e[i].v])any_cut=1;if (!fa&&child>=2)any_cut=1;}elselow[x]=min(low[x],dfn[e[i].v]);
}
void work()
{n=in();m=in();k=in();X[0]=0;Y[0]=0;cnt=0;ID=0;tot=0;any_cut=0;e[1].v=0;for (int x,y,i=1;i<=k;++i){x=in();y=in();a[i]=(node){0,x,y};if (x>1) X[++X[0]]=x-1,b[++ID]=(node){0,x-1,y};if (x<n) X[++X[0]]=x+1,b[++ID]=(node){0,x+1,y};X[++X[0]]=x;if (y>1) Y[++Y[0]]=y-1,b[++ID]=(node){0,x,y-1};if (y<m) Y[++Y[0]]=y+1,b[++ID]=(node){0,x,y+1};Y[++Y[0]]=y;    if (x>1&&y>1) b[++ID]=(node){0,x-1,y-1};if (x>1&&y<m) b[++ID]=(node){0,x-1,y+1};if (x<n&&y>1) b[++ID]=(node){0,x+1,y-1};if (x<n&&y<m) b[++ID]=(node){0,x+1,y+1};}if ((LL)n*m-k<=1) return void(puts("-1"));memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low));memset(first,0,sizeof(first));up=lef=M,down=rit=0;for (int i=1;i<=X[0];++i)lef=min(X[i],lef),rit=max(X[i],rit);for (int i=1;i<=Y[0];++i)up=min(Y[i],up),down=max(Y[i],down);if (lef>1) --lef;if (rit<n) ++rit;if (up>1) --up;if (down<m) ++down;X[++X[0]]=lef;X[++X[0]]=rit;Y[++Y[0]]=up;Y[++Y[0]]=down;sort(X+1,X+X[0]+1);X[0]=unique(X+1,X+X[0]+1)-X-1;sort(Y+1,Y+Y[0]+1);Y[0]=unique(Y+1,Y+Y[0]+1)-Y-1;for (int i=1;i<=X[0];++i)b[++ID]=(node){0,X[i],Y[1]},b[++ID]=(node){0,X[i],Y[Y[0]]};for (int i=1;i<=Y[0];++i)b[++ID]=(node){0,X[1],Y[i]},b[++ID]=(node){0,X[X[0]],Y[i]};key=0;sort(a+1,a+k+1);sort(b+1,b+ID+1);ID=unique(b+1,b+ID+1)-b-1;for (int i=1;i<=k;++i)a[i].x=lower_bound(X+1,X+X[0]+1,a[i].x)-X,a[i].y=lower_bound(Y+1,Y+Y[0]+1,a[i].y)-Y;for (int i=1;i<=ID;++i)b[i].x=lower_bound(X+1,X+X[0]+1,b[i].x)-X,b[i].y=lower_bound(Y+1,Y+Y[0]+1,b[i].y)-Y,b[i].id=i;for (int t=1,tt=1,i=1;i<=ID;++i){node tmp=b[i];while (t<=k&&a[t]<tmp) ++t;if (t>=1&&t<=k&&a[t]==tmp) continue;++cnt;tmp.x++;while (t<=k&&a[t]<tmp) ++t;while (tt<=ID&&b[tt]<tmp) ++tt;if (tt>=1&&tt<=ID&&b[tt].y==b[i].y&&b[tt].x>b[i].x&&(t<1||t>k||b[tt]<a[t]))add(b[i].id,b[tt].id);}key=1;sort(a+1,a+k+1);sort(b+1,b+ID+1);for (int t=1,tt=1,i=1;i<=ID;++i){node tmp=b[i];while (t<=k&&a[t]<tmp) ++t;if (t>=1&&t<=k&&a[t]==tmp) continue;tmp.y++;while (t<=k&&a[t]<tmp) ++t;while (tt<=ID&&b[tt]<tmp) ++tt;if (tt>=1&&tt<=ID&&b[tt].x==b[i].x&&b[tt].y>b[i].y&&(t<1||t>k||b[tt]<a[t]))add(b[i].id,b[tt].id);}if (e[1].v) dfs(e[1].v,0);if ((LL)n*m-k==2&&(dfn[0]==2||!k)) return void(puts("-1"));if ((LL)n*m-k>=2&&dfn[0]<cnt) return void(puts("0"));if (dfn[0]==cnt&&any_cut) return void(puts("1"));if (n==1||m==1) return void(puts("1"));puts("2");
}
main()
{for (T=in();T;--T) work();
}

【NOI2016】网格,离散化+求割点相关推荐

  1. hdu 4587 2013南京邀请赛B题/ / 求割点后连通分量数变形。

    题意:求一个无向图的,去掉两个不同的点后最多有几个连通分量. 思路:枚举每个点,假设去掉该点,然后对图求割点后连通分量数,更新最大的即可.算法相对简单,但是注意几个细节: 1:原图可能不连通. 2:有 ...

  2. uva 315 (poj 1144 求割点)

    题意:给你一张无向图,求割点的个数. 思路:输入稍微处理一下接着直接套模版. 1 #include <iostream> 2 #include <cstdio> 3 #incl ...

  3. POJ1144:Network(无向连通图求割点)

    题目:http://poj.org/problem?id=1144 求割点.判断一个点是否是割点有两种判断情况: 如果u为割点,当且仅当满足下面的1条 1.如果u为树根,那么u必须有多于1棵子树 2. ...

  4. POJ1144——网络(求割点)

    描述 电话线公司(TLC)正在建立一个新的电话有线网络.它们连接多个由1到N的整数编号的地方.没有两个地方有相同的数字.线路是双向的,并且总是连接在一起的两个地方,并且在每个地方线路结束在电话交换机中 ...

  5. POJ 1144 Network(无向图连通分量求割点)

    题目地址:POJ 1144 求割点.推断一个点是否是割点有两种推断情况: 假设u为割点,当且仅当满足以下的1条 1.假设u为树根,那么u必须有多于1棵子树 2.假设u不为树根.那么(u,v)为树枝边. ...

  6. POJ1523:SPF(无向连通图求割点)

    题目:http://poj.org/problem?id=1523 题目解析: 注意题目输入输入,防止PE,题目就是求割点,并问割点将这个连通图分成了几个子图,算是模版题吧. #include < ...

  7. [UVA315]Network(tarjan, 求割点)

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  8. 图论 —— 图的连通性 —— Tarjan 求割点与桥

    [概念] 1.割点 1)割点:删除某点后,整个图变为不连通的两个部分的点 2)割点集合:在一个无向图中删除该集合中的所有点,能使原图变成互不相连的连通块的点的集合 3)点连通度:最小割点集合点数 如上 ...

  9. loj 1063(求割点个数)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26780 思路:判断一个点是否是割点的两个条件:1.如果一个点v是根 ...

最新文章

  1. Django+Bootstrap+Mysql 搭建个人博客(五)
  2. 重定位(搜索KERNEL32.DLL得到API地址)
  3. MVC的开发模式简单介绍
  4. sql 把多列内容合并
  5. SSH-CLIENT : gSTM
  6. TCP状态中 time_wait 的作用?
  7. Vuejs-踩坑/注意事项记录
  8. 经典逻辑编程题(本文用python实现)
  9. 转:Linux 2.4.x内核软中断机制
  10. 你掉进过“伪敏捷”的陷阱吗?
  11. 演示:思科交换机的Telnet管理与SSH管理
  12. 计算机专业英语第五章ppt,计算机专业英语课件5.ppt
  13. 计算机网络网络层之数据报网络
  14. 严重性 代码 说明 项目 文件 行 警告 C4819 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 opencv-05 d:\opencv\o
  15. 程序员进阶之路的10本必读书目
  16. java+mysql学科竞赛管理系统(java,web)
  17. mysql数据类型内存_MySQL数据库基本功-常用数据类型介绍和优化技巧
  18. ROS学习----依据ROS入门教程,整理的ROS命令
  19. DoIP(五)—— UDSonIP
  20. Java如何使用new来创建对象

热门文章

  1. 60秒计时器的仿真电路_DS1302的电子万年历,时间、闹钟可调,带温度农历显示,原理图、仿真和代码...
  2. CompSNN: A Lightweight Spiking Neural Network Based on Spatiotemporally Compressive Spike Features
  3. 【numpy】numpy.random.uniform()函数
  4. git提交时发现iml文件没有被排除
  5. 在Windows上编译Spark源码
  6. Spark: sortBy和sortByKey函数详解
  7. MongoDB数据库操作---mongoose操作
  8. day21 java的数字类
  9. 给定一个整数数组,判断是否存在重复元素。
  10. 旋转数组(右旋转,js实现,unshift,splicec实现)