题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5652

题意:

  输入T,接下来T个样例,每个样例输入n,m代表图的大小,接下来n行,每行m个数,代表图,0表示这个位置可以走,1表示走不了,接下来q个点的位置,表示第q个时间这个点的值变成1,就不能走了,问在什么时间开始从最上面无法走到最下面。

最后还是看了别人博客(不争气啊),用并查集的思路就是先给每个点编号,然后用两个数组pre1,pre2数组方便存储编号为i的点所在的点集(并查集)里面最左和最右的值,当最左的值为0,最右的值为m-1是说明这个连续的点集已经把上下隔断了。只是大致说了下,看代码,有人也用了二分+BFS,对q个时间段进行二分,用BFS判断上下是否被隔断,应该是这样,没用这种方法写。

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<set>
#include<cstdio>
#include<string>
#include<deque>
using namespace std;
typedef long long LL;
#define eps 1e-8
#define INF 0x3f3f3f3f
#define maxn 505
int n,m,k,t,ans,id;
char str[maxn][maxn];
int num[maxn][maxn];//记录点str[i][j]对应的编号
int pre1[maxn*maxn],pre2[maxn*maxn];//两个数组记录祖先,祖先编号对m取模得出的值就是左右两边最值
int dir[][]={,,,-,,,-,,,,,-,-,,-,-};//八个方向
int find1(int a)
{
if(a==pre1[a])
return a;
return pre1[a]=find1(pre1[a]);
}
void combine1(int x,int y)
{
int a=find1(x);
int b=find1(y);
if(a%m<b%m)//祖先编号对m取模值较小的为合并之后的祖先
pre1[b]=a;
else
pre1[a]=b;
}
int find2(int a)
{
if(a==pre2[a])
return a;
return pre2[a]=find2(pre2[a]);
}
void combine2(int x,int y)
{
int a=find2(x);
int b=find2(y);
if(a%m>b%m)//祖先编号对m取模值较大的为合并之后的祖先
pre2[b]=a;
else
pre2[a]=b;
}
void bianhao()
{
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
num[i][j]=++id;//给每个点编号
pre1[id]=id;
pre2[id]=id;
}
}
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
if(str[i][j]=='')
{
for(int k=;k<;k++)//搜索每个黑块周围
{
int a=i+dir[k][];
int b=j+dir[k][];
if(a>=&&a<n&&b>=&&b<m&&str[a][b]=='')
{
combine1(num[i][j],num[a][b]);
combine2(num[i][j],num[a][b]);
}
}
}
}
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
ans=-;
id=-;
for(int i=;i<n;i++)
scanf("%s",str[i]);
bianhao();
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
int a=find1(num[i][j]);
int b=find2(num[i][j]);
if(a%m==&&b%m==m-)//在山峰升起前可能两国可能已经隔断
{
ans=;
break;
}
}
if(ans!=-)
break;
}
int q;
scanf("%d",&q);
for(int s=;s<=q;s++)
{
int x,y;
scanf("%d%d",&x,&y);
str[x][y]='';//山峰升起
if(ans!=-)
continue;
for(int i=;i<;i++)
{
int a=x+dir[i][];
int b=y+dir[i][];
if(a>=&&a<n&&b>=&&b<m&&str[a][b]=='')
{
combine1(num[x][y],num[a][b]);
combine2(num[x][y],num[a][b]);
int l=find1(num[x][y]);
int r=find2(num[x][y]);
if(l%m==&&r%m==m-)//黑色块所在点集的左右两最值达到左右边界
{
ans=s;
break;
}
}
}
}
printf("%d\n",ans);
}
return ;
}

思维+并查集 hdu5652的更多相关文章

  1. Gym - 101243F Vitamins(思维+并查集)

    题意 有三种药丸,白色W>红色R>蓝色B,给你m个约束条件,问你n个药丸的颜色,不能确定颜色输出‘?’ 题解 如果1<2<3,只要找到2就能确定1和3的颜色 如果2=4,只要确 ...

  2. cf 之lis+贪心+思维+并查集

    https://codeforces.com/contest/1257/problem/E 题意:有三个集合集合里面的数字可以随意变换位置,不同集合的数字,如从第一个A集合取一个数字到B集合那操作数+ ...

  3. 牛客网多校第4场 J Hash Function 【思维+并查集建边】

    题目链接:戳这里 学习博客:戳这里 题意: 有n个空位,给一个数x,如果x%n位数空的,就把x放上去,如果不是空的,就看(x+1)%n是不是空的. 现在给一个已经放过数的状态,求放数字的顺序.(要求字 ...

  4. codeforces 1013B 【思维+并查集建边】

    题目链接:戳这里 转自:参考博客 题意:给一个n*m的矩阵,放入q个点,这q个点之间的关系是,若已知这样三个点(x1,y1),(x2,y1),(x1,y2),可以在(x2,y2)处生成一个新的点,对于 ...

  5. CodeForces - 1243D (思维+并查集)

    题意 https://vjudge.net/problem/CodeForces-1243D 有一张完全图,n个节点 有m条边的边权为1,其余的都为0 这m条边会给你 问你这张图的最小生成树的权值 思 ...

  6. hdu5652 India and China Origins(并查集)

    India and China Origins  Accepts: 49  Submissions: 426  Time Limit: 2000/2000 MS (Java/Others)  Memo ...

  7. hdu6074[并查集+LCA+思维] 2017多校4

    看了标答感觉思路清晰了许多,用并查集来维护全联通块的点数和边权和. 用另一个up[]数组(也是并查集)来保证每条边不会被重复附权值,这样我们只要将询问按权值从小到大排序,一定能的到最小的边权和与联通块 ...

  8. 【春训团队赛第四场】补题 | MST上倍增 | LCA | DAG上最长路 | 思维 | 素数筛 | 找规律 | 计几 | 背包 | 并查集

    春训团队赛第四场 ID A B C D E F G H I J K L M AC O O O O O O O O O 补题 ? ? O O 传送门 题目链接(CF Gym102021) 题解链接(pd ...

  9. CF思维联系--CodeForces - 218C E - Ice Skating (并查集)

    题目地址:24道CF的DIv2 CD题有兴趣可以做一下. ACM思维题训练集合 Bajtek is learning to skate on ice. He's a beginner, so his ...

随机推荐

  1. [Flex+JAVA]建立Flex+java项目,并实现基本功能

    1新建JAVA WEB项目 新建后的web文件包截图 3添加Flex项目,右键,添加.更改项目类型,天剑Flex项目类型

  2. c#调用带输出参数的存储过程

    sql server中编写一个存储过程: CREATE PROCEDURE ProGetPWD @username varchar(20), @password varchar(20) OUTPUT ...

  3. leetcode997

    class Solution: def findJudge(self, N: int, trust: 'List[List[int]]') -> int: if N==1 and len(tru ...

  4. 递归获取包下的class文件

    ```java(这个居然隐藏不了) public class TestUrl { public static void main(String[] args) { String pageName = ...

  5. using关键字在C#中的3种用法

    using 关键字有两个主要用途:  (一).作为指令,用于为命名空间创建别名或导入其他命名空间中定义的类型.  (二).作为语句,用于定义一个范围,在此范围的末尾将释放对象. (一).作为指令 1. ...

  6. delphi异常捕获try except语句 和 try finally语句用法

    原文地址:delphi try except语句 和 try finally语句用法以及区别作者:1865898133 一直写程序都没管他们,也尽量很少用,今天终于想把他给弄个明白,在网上找来,记下! ...

  7. Emac

    https://emacs-china.org/ 启动 console模式的emacs,$emacs -nw 学习参考: 1)<21天精通emacs> 2)Emacs常用命令简集. 3)& ...

  8. 计算机&通信词典

    目录 A B C Cgroups D E F G H I J K L M N NFV NFV ISG O ONF P Q R Rewrite S T U V VNFI W X Y Z A B C Cg ...

  9. git rebase 合并提交 解决超过100M文件的提交不能推送问题

    git log 现在可以看到有3个提交: change 1.mp4 size to small //发现不能推送,又改回小于100M add 1.mp4 big 改变为超过100M add 1.mp4 ...

  10. 如何用java读取properties文件

    1.Properties类与Properties配置文件 Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存属性集.不过Properties有特殊的地 ...