BZOJ 4423: [AMPPZ2013]Bytehattan 并查集 平面图转对偶图

探讨了在一张n*n网格图中,通过删除边来判断顶点连通性的算法实现。采用并查集维护网格及其对偶图的连通状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4423: [AMPPZ2013]Bytehattan

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 314  Solved: 209
[Submit][Status][Discuss]

Description

比特哈顿镇有n*n个格点,形成了一个网格图。一开始整张图是完整的。
有k次操作,每次会删掉图中的一条边(u,v),你需要回答在删除这条边之后u和v是否仍然连通。

Input

第一行包含两个正整数n,k(2<=n<=1500,1<=k<=2n(n-1)),表示网格图的大小以及操作的个数。
接下来k行,每行包含两条信息,每条信息包含两个正整数a,b(1<=a,b<=n)以及一个字符c(c=N或者E)。
如果c=N,表示删除(a,b)到(a,b+1)这条边;如果c=E,表示删除(a,b)到(a+1,b)这条边。
数据进行了加密,对于每个操作,如果上一个询问回答为TAK或者这是第一个操作,那么只考虑第一条信息,否则只考虑第二条信息。
数据保证每条边最多被删除一次。

Output

输出k行,对于每个询问,如果仍然连通,输出TAK,否则输出NIE。

Sample Input

3 4
2 1 E 1 2 N
2 1 N 1 1 N
3 1 N 2 1 N
2 2 N 1 1 N

Sample Output

TAK
TAK
NIE
NIE

强制在线

如果可以离线的话 用 时光逆流 并查集 解决


每删去一条边,就在两网格之间连一条边

当出现两点不被同一个墙一样的分界线围起来的话就不连通

其实就是在原图删边,在对偶图连边

用并查集维护一下


#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return x*f;
}
inline void print(int x)
{
	if(x<0)putchar('-'),x=-x;
	if(x>=10)print(x/10);putchar('0'+x%10);
}
const int N=1600;
int pos[N][N],fa[N*N];
inline int find(int u)
{
	int t=u;
	while(t!=fa[t])t=fa[t];
	while(u!=fa[u])u=fa[u],fa[u]=t;
	return u;
}
int main()
{
	int n=read(),k=read();int tmp=0;
	for(int i=0;i<=n;i++)for(int j=0;j<=n;j++)pos[i][j]=++tmp;
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)fa[pos[i][j]]=pos[i][j];
	for(int i=0;i<=n;i++)fa[pos[0][i]]=fa[pos[i][0]]=1,fa[pos[i][n]]=1,fa[pos[n][i]]=1;
	bool ans=1;
	while(k--)
	{
		int u=read(),v=read();char ch[2];scanf("%s",ch);
		if(ans){int ua=read(),va=read();char cha[2];scanf("%s",cha);}
		else {u=read();v=read();scanf("%s",ch);}
		int a=find(pos[u][v]),b;
		if(ch[0]=='E')b=find(pos[u][v-1]);
		else b=find(pos[u-1][v]);
		if(a==b)ans=0;
		else 
		{fa[a]=b;ans=1;}
		if(ans)puts("TAK");
		else puts("NIE");
	}
	return 0;
}
/*
3 4
2 1 E 1 2 N
2 1 N 1 1 N
3 1 N 2 1 N
2 2 N 1 1 N

TAK
TAK
NIE
NIE
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值