Codeforces325 D【並查集維護連通性】
阿新 • • 發佈:2018-12-24
思路:
因為是環,所以可以複製一下圖,先判斷一下和他是不是和與他相鄰的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\n", ans); return 0; }