首页 > 代码库 > (并查集)Codeforces 325 D-Reclamation

(并查集)Codeforces 325 D-Reclamation

 

技术分享

借用 链接 的题意和解法分析的图片。

对于这种环的形式,先用常用的手段复制一份在右边。每次加点的过程只要看加完之后能不能通过已有的格子联通,如果联通则显然已经形成了一个环。这里判断联通我采用的办法是,分别看两个点八个方向是否联通的无脑办法。想法很明确,但实现的过程中要注意一些细节,如列坐标<=0或>2*m的处理。

  1 #include <iostream>
  2 #include <string>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <queue>
  8 #include <set>
  9 #include <map>
 10 #include <list>
 11 #include <vector>
 12 #include <stack>
 13 #define mp make_pair
 14 //#define P make_pair
 15 #define MIN(a,b) (a>b?b:a)
 16 //#define MAX(a,b) (a>b?a:b)
 17 typedef long long ll;
 18 typedef unsigned long long ull;
 19 const int MAX=18e6+5;
 20 const int MAX_V=1e3+5;
 21 const int INF=1e9+5;
 22 const ll INF2=4e18+5;
 23 const double M=4e18;
 24 using namespace std;
 25 const int MOD=1e9+7;
 26 typedef pair<ll,int> pii;
 27 const double eps=0.000000001;
 28 #define rank rankk
 29 int an;
 30 int par[MAX];//父亲
 31 int rank[MAX];//树的高度
 32 //初始化n个元素
 33 void init(int n)
 34 {
 35     for(int i=0;i<n;i++)
 36     {
 37         par[i]=i;
 38         rank[i]=0;
 39     }
 40 }
 41 //查询树的根,期间加入了路径压缩
 42 int find(int x)
 43 {
 44     if(par[x]==x)
 45         return x;
 46     else
 47         return par[x]=find(par[x]);
 48 }
 49 //合并x和y所属的集合
 50 void unite(int x,int y)
 51 {
 52     x=find(x);
 53     y=find(y);
 54     if(x==y)
 55         return ;
 56     if(rank[x]<rank[y])
 57         par[x]=y;
 58     else
 59     {
 60         par[y]=x;
 61         if(rank[x]==rank[y])
 62             rank[x]++;
 63     }
 64 }
 65 //判断x和y是否属于同一个集合
 66 bool same(int x,int y)
 67 {
 68     return find(x)==find(y);
 69 }
 70 int n,m,q;
 71 int a[MAX];
 72 int dx[8]={-1,-1,-1,0,0,1,1,1};
 73 int dy[8]={-1,0,1,-1,1,-1,0,1};
 74 bool vi[3005][6005];
 75 int idx(int x,int y)//x行y列
 76 {
 77     return (x-1)*2*m+y;
 78 }
 79 bool check(int x,int &y)
 80 {
 81     return x>=1&&x<=n&&y>=1&&y<=2*m;
 82 }
 83 int solve(int x,int y)
 84 {
 85     int x2=x,y2=y+m;
 86     for(int i=0;i<8;i++)
 87     {
 88         int x1=x+dx[i],y1=y+dy[i];
 89         if(y1<1)
 90             y1+=2*m;
 91         else if(y1>2*m)
 92             y1-=2*m;
 93         if(check(x1,y1)&&vi[x1][y1])
 94         {
 95             for(int j=0;j<8;j++)
 96             {
 97                 int x3=x2+dx[j],y3=y2+dy[j];
 98                 if(check(x3,y3)&&vi[x3][y3])
 99                     if(same(idx(x3,y3),idx(x1,y1)))
100                        return 0;
101             }
102         }
103     }
104     return 1;
105 }
106 int main()
107 {
108     scanf("%d%d%d",&n,&m,&q);
109     if(m==1)
110         return 0*printf("0\n");
111     init(2*n*m+3);
112     int Max=2*m;
113     while(q--)
114     {
115         int x,y;
116         scanf("%d%d",&x,&y);
117             if(solve(x,y))
118             {
119                 vi[x][y]=vi[x][y+m]=true;
120                 ++an;
121                 for(int i=0;i<8;i++)
122                 {
123                     int x1=x+dx[i],y1=y+dy[i];
124                     if(y1<=0)
125                         y1+=Max;
126                     else if(y1>Max)
127                         y1-=Max;
128                     if(check(x1,y1)&&vi[x1][y1])
129                         unite(idx(x,y),idx(x1,y1));
130                     y1+=m;
131                     if(y1<=0)
132                         y1+=Max;
133                     else if(y1>Max)
134                         y1-=Max;
135                     if(check(x1,y1)&&vi[x1][y1])
136                         unite(idx(x,y+m),idx(x1,y1));
137                 }
138             }
139     }
140     printf("%d\n",an);
141     return 0 ;
142 }

 

(并查集)Codeforces 325 D-Reclamation