1. 程式人生 > >(並查集)Codeforces 325 D-Reclamation

(並查集)Codeforces 325 D-Reclamation

name clam .cn 每次 .html con ret ring true

技術分享

借用 鏈接 的題意和解法分析的圖片。

對於這種環的形式,先用常用的手段復制一份在右邊。每次加點的過程只要看加完之後能不能通過已有的格子聯通,如果聯通則顯然已經形成了一個環。這裏判斷聯通我采用的辦法是,分別看兩個點八個方向是否聯通的無腦辦法。想法很明確,但實現的過程中要註意一些細節,如列坐標<=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