NOJ 1301 Gopher Hole 并查集好题 n*n矩阵上打洞 不相连洞的个数

来源:互联网 发布:qq网络营销软件 编辑:程序博客网 时间:2024/05/08 13:41
  • [1301] Gopher Hole

  • 时间限制: 1000 ms 内存限制: 65535 K
  • 问题描述
  • 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 5Out 0 0POut 1 0Out 2 2P
  • 样例输出
  • 12
  • 提示
  • 来源
  • Hungar

    题意:

    死月最爱讲故事了,这次他讲了个很有趣的故事。很久很久以前,有一只地鼠,他很调皮,很喜欢打洞。这次他来到一块 N * N 的地域,然后开始打洞。当输入是Out的时候,表示他将在(x, y)打洞,当有两个洞是拥有公共的边时,那么这两个洞是连通的,也就是说是属于同一个洞的。 问一共会有多少个洞
     
     
    那么,每挖一次洞,就使用一次并查集。
    #include<stdio.h>#include<string.h>int parent[111111],rank[111111];int map[111][111];int dir[4][2]={0,1,0,-1,1,0,-1,0};int find_root(int x){return parent[x]==x?x:(parent[x]=find_root(parent[x]));//路径压缩  这里不一样了 多了个赋值//return x==parent[x]?x:find_root(parent[x]);}int main(){int m,n,i,x,j,y,n1,n2,pos1,pos2;char ss[100];while(scanf("%d %d",&n,&m)!=EOF){int ans=0;memset(map,0,sizeof(map));int mid=n*n+10;for(i=0;i<mid;i++){parent[i]=i;rank[i]=1;}for(i=0;i<m;i++){scanf("%s",ss);if(ss[0]=='O'){scanf("%d %d",&x,&y);if(map[x][y]==1) continue;//注意这里啊  防止重复在某个点挖洞 否则会产生重复计算map[x][y]=1;for(j=0;j<4;j++){int xx=x+dir[j][0];int yy=y+dir[j][1];                    if(xx>=0&&xx<n&&yy>=0&&yy<n){if(map[xx][yy]==0) continue;          else break;}}if(j==4)  {ans++; continue;}//如果这个洞 周围全不是洞 那么洞的数量加1                int p=1;//表示 x y点产生的一个洞for(j=0;j<4;j++){int xx=x+dir[j][0];int yy=y+dir[j][1];if(xx<0||xx>=n||yy<0||yy>=n||map[xx][yy]==0) continue;pos1=x*n+y;pos2=xx*n+yy;n1=find_root(pos1);n2=find_root(pos2);if(n1!=n2)               {     p--;//如果合并了  说明少了一个洞 if(rank[n1]>=rank[n2])        {                         parent[n2]=n1;             rank[n1]+=rank[n2];          }                    else                {                    parent[n1]=n2;          rank[n2]+=rank[n1];         }   }}ans+=p;}else printf("%d\n",ans);}}return 0;}