借用 链接 的题意和解法分析的图片。
对于这种环的形式,先用常用的手段复制一份在右边。每次加点的过程只要看加完之后能不能通过已有的格子联通,如果联通则显然已经形成了一个环。这里判断联通我采用的办法是,分别看两个点八个方向是否联通的无脑办法。想法很明确,但实现的过程中要注意一些细节,如列坐标<=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 }