zoukankan      html  css  js  c++  java
  • Codeforces325 D【并查集维护连通性】

    参考:大牛blog

    思路:

    因为是环,所以可以复制一下图,先判断一下和他是不是和与他相邻的8个之一的一个障碍使得构成了一个环,环就是一个连通,用并查集维护即可;

    如果没有就ans++,然后并把这个点加入。

    大致意思就是这样。

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cstdlib>
    #include <ctime>
    #include <cmath>
    #include <map>
    #include <set>
    using namespace std;
    
    const int maxn=3000*3000*2+100;
    const int dx[8]={-1, -1, -1, 0, 0, 1, 1, 1};
    const int dy[8]={-1, 0, 1, -1, 1, -1, 0, 1};
    
    int n, r, c, ti;
    int ans;
    int fa[maxn];
    bool vis[3010][6010];
    int mark[maxn];
    
    int find(int cur)
    {
        if (fa[cur]<0) return cur;
        else return (find(fa[cur]));
    }
    void Union(int u, int v)
    {
        u=find(u);
        v=find(v);
        if (u==v) return;
        if (fa[u]>fa[v]) swap(u, v);
        fa[u]+=fa[v];
        fa[v]=u;
    }
    bool check(int &x1, int &y1)
    {
        if (x1<1 || x1>r) return false;
        if (y1==0) y1=c;
        else if (y1>c) y1=1;
        if (!vis[x1][y1]) return false;
        return true;
    }
    void merge(int x, int y)
    {
        int nid=(x-1)*c+y;
        for (int i=0; i<8; ++i)
        {
            int x1=x+dx[i];
            int y1=y+dy[i];
            if (check(x1, y1)) Union(nid, (x1-1)*c+y1);
        }
    }
    bool get_list(int x, int y, int id)
    {
        for (int i=0; i<8; ++i)
        {
            int x1=x+dx[i];
            int y1=y+dy[i];
            if (!check(x1, y1)) continue;
            int tmp=find((x1-1)*c+y1);
            if (id && mark[tmp]==ti-1) return false;
            mark[tmp]=ti;
        }
        return true;
    }
    
    void solve()
    {
        if (c==1) return;
        c*=2;
    
        for (int i=1; i<=r; ++i)
            for (int j=1; j<=c; ++j)
                fa[(i-1)*c+j]=-1;
    
        for (int i=1; i<=n; ++i)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            ++ti;
            get_list(x, y, 0);
            ++ti;
            bool flag=get_list(x, y+c/2, 1);
            if (!flag) continue;
            ++ans;
            merge(x, y);
            merge(x, y+c/2);
            vis[x][y]=true;
            vis[x][y+c/2]=true;
        }
    }
    
    int main()
    {
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        scanf("%d%d%d", &r, &c, &n);
        solve();
        printf("%d
    ", ans);
        return 0;
    }


  • 相关阅读:
    使用C#调用系统API实现锁定计算机
    阶段性总结
    心情状态所困
    VMware虚拟机网络配置相关备忘
    数据库学习第一篇
    给window xp sp2设置共享文件夹
    转报竞赛实操试题
    数据库视频笔记
    Android开发从零开始,搭建交叉编译环境
    排故总结
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777501.html
Copyright © 2011-2022 走看看