NBUT 1301-Gopher Hole【并查集+查询】 难度:**

题意:

Death-Moon loves telling stories.
Some days ago, he told us a funny story.

Long long ago, there is a hamster who is so naughty. Now, he comes to a place likes a N * N square. so, he is so excited to drill holes underground.

输入
Input until EOF.
Fisrt input two integers N (3 <= N < 100) and M (0 < M <2000). N is the side of N * N ground, M is the number of operations.

Then follow M lines.
Each line is a command:

Out x y : Hamster will get out at (x, y) from underground. So, place (x, y) will be a hole.
P : Calculate out the number of the holes and output (Two holes are connected when they share an edge).
If two holes are connected, it means it is one hole.
输出
For each ‘P’ command, output the number of the holes. Maybe hamster will get out at the same place more than once.
样例输入
3 5
Out 0 0
P
Out 1 0
Out 2 2
P
样例输出
1
2

题解:

题意可以概括为:相邻的洞可以连接为一个洞,挖洞的同时不断查询洞的个数。像这种n并1的题肯定是用并查集来解决。按照模板题的写法,每次查询个数需要整体遍历一遍,放在这道题一定会超时。因此我们可以维护一个sum值,每次加入新洞后,sum+=1-cot,其中cot表示加入这个洞后,该洞四周一共有几个独立的洞,查找几个独立的洞的方法就是分别比较四周洞的根结点是否相同(当然四周不一定都有洞),这样每次查询操作近似为O(1)。
(代码里的并查路径压缩函数写重了,不要介意哈)

代码:

#include<stdio.h>
int a[10005];
int findtop(int x)
{
	return x==a[x]?x:a[x]=findtop(a[x]);
}
int checktop(int x)
{
	return x==a[x]?x:checktop(a[x]);
}
int main()
{
	int n,m,x,y,t,sum,k1,k2,b[10];
	char ch[10];
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		for(int i=0;i<=(n+1)*(n+1);i++)a[i]=-1;
		sum=0;k1=0;
		while(m--)
		{
			scanf("%s",ch);
			if(ch[0]=='O')
			{
				scanf("%d%d",&x,&y);
				t=x*n+y;
				if(a[t]!=-1)continue;
				a[t]=t;
				k1=0;
				if(x!=n-1)if(a[t+n]!=-1){b[k1]=checktop(t+n);k1++;}
				if(x!=0)if(a[t-n]!=-1){b[k1]=checktop(t-n);k1++;}
				if(y!=n-1)if(a[t+1]!=-1){b[k1]=checktop(t+1);k1++;}
				if(y!=0)if(a[t-1]!=-1){b[k1]=checktop(t-1);k1++;}
				int temp=k1;
				for(int i=0;i<temp;i++)
				{
					for(int j=i+1;j<temp;j++)
					{
						if(b[i]==b[j]&&b[i]!=-1)
						{
							k1--;
							b[j]=-1;
						}
					}
				}
				if(x!=n-1)if(a[t+n]!=-1&&a[findtop(t)]!=a[findtop(t+n)])a[findtop(t)]=a[findtop(t+n)];
				if(x!=0)if(a[t-n]!=-1&&a[findtop(t)]!=a[findtop(t-n)])a[findtop(t)]=a[findtop(t-n)];
				if(y!=n-1)if(a[t+1]!=-1&&a[findtop(t)]!=a[findtop(t+1)])a[findtop(t)]=a[findtop(t+1)];
				if(y!=0)if(a[t-1]!=-1&&a[findtop(t)]!=a[findtop(t-1)])a[findtop(t)]=a[findtop(t-1)];
				sum=sum+1-k1;
			}
			else if(ch[0]=='P')printf("%d\n",sum);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_42921101/article/details/104341016