zoukankan      html  css  js  c++  java
  • UVA 572 油田连通块-并查集解决

    题意:8个方向如果能够连成一块就算是一个连通块,求一共有几个连通块。

    分析:网上的题解一般都是dfs,但是今天发现并查集也可以解决,为了方便我自己理解大神的模板,便尝试解这道题目,没想到过了。。。

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <sstream>
      4 #include <cmath>
      5 #include <cstring>
      6 #include <cstdlib>
      7 #include <string>
      8 #include <vector>
      9 #include <map>
     10 #include <set>
     11 #include <queue>
     12 #include <stack>
     13 #include <algorithm>
     14 #define ll long long
     15 #define mem(m, a) memset(m, a, sizeof(m))
     16 #define repu(i, a, b) for(int i = a; i < b; i++)
     17 #define maxn 1100
     18 const double PI=-acos(-1.0);
     19 using namespace std;
     20 struct Node
     21 {
     22     int val, x, y;
     23     bool operator < (const Node a)const
     24     {
     25         return val > a.val;
     26     }
     27     Node(int v=0, int x=0, int y=0):val(v), x(x), y(y) {}
     28 } nd[maxn*maxn];
     29 struct Query
     30 {
     31     int h, id;
     32     bool operator < (const Query a)const
     33     {
     34         return h>a.h;
     35     }
     36     Query(int h=0, int id=0):h(h), id(id) {}
     37 } q[100010];
     38 bool vis[maxn][maxn];
     39 int n, m, pre[maxn*maxn];
     40 const int dx[]= {0, 0, -1, 1, 1, 1, -1, -1};
     41 const int dy[]= {1, -1, 0, 0, 1, -1, 1, -1};
     42 int Find(int x)
     43 {
     44     if(pre[x] == -1) return x;
     45     return pre[x] = Find(pre[x]);
     46 }
     47 bool OK(int x, int y)
     48 {
     49     return x && y && x<=n && y<=m;
     50 }
     51 int judge(int x, int y)
     52 {
     53     int v[5], cnt=0;
     54     for(int i=0; i<8; i++)///寻找他周围的四个数字是哪些集合的
     55     {
     56         int nx=x+dx[i], ny=y+dy[i];
     57         if(OK(nx, ny) && vis[nx][ny])///已经遍历过的
     58         {
     59             int t = Find(m*(nx-1)+ny);
     60             v[cnt++] = t;
     61         }
     62     }
     63     sort(v, v+cnt);
     64     cnt = unique(v, v+cnt)-v;
     65     for(int i=0; i < cnt; i++)
     66         pre[v[i]] = m*(x-1)+y;///把筛选下来的全都归入(x,y)中
     67     return 1 - cnt;///返回的值也只有-1,0,1
     68 }
     69 int main()
     70 {
     71     char c[110][110];
     72     int T, t, v;
     73     while(~scanf("%d%d", &n, &m) ,n + m)
     74     {
     75         getchar();
     76         int tot=0;
     77         repu(i,1,n+1)
     78         gets(c[i]);
     79         repu(i,1,n+1)
     80         {
     81             repu(j,0,m)
     82             {
     83                 if(c[i][j] == '*')
     84                     nd[tot]=Node(1, i, j+1);
     85                 else
     86                     nd[tot]=Node(2, i, j+1);
     87                 tot++;
     88             }
     89         }
     90         ///都是从大到小
     91         sort(nd, nd+tot);
     92         memset(vis, 0, sizeof vis);
     93         memset(pre, -1, sizeof pre);
     94         int cnt=0,j = 0;
     95         for(; nd[j].val > 1 && j < tot; j++)
     96         {
     97             ///如果这个点比所查询的点大,则可以加入其坐标
     98             cnt += judge(nd[j].x, nd[j].y);
     99             vis[nd[j].x][nd[j].y]=1;
    100         }
    101         printf("%d
    ",cnt);
    102     }
    103     return 0;
    104 }
    105 /*
    106 3 5
    107 *@*@*
    108 **@**
    109 *@*@*
    110 */
    View Code

    借助的是UVA 1665 大神的模板

  • 相关阅读:
    水晶报表基础操作技巧收藏
    注册表里相应的
    .Net 中的反射(动态创建类型实例) Part.4动态创建对象
    .Net 中的反射(查看基本类型信息) Part.2
    Javascript多级菜单
    诡异的中毒现象
    js魔力代码
    Silverlight入门教程
    Silverlight 2.0中文学习资源集萃
    jatoolsPrinter 2手册
  • 原文地址:https://www.cnblogs.com/ACMERY/p/4836814.html
Copyright © 2011-2022 走看看