自从懂了并查集只后,感觉好多题都是并查集,就像哪一天的字典树一样,这道题一看就是一个并查集,最后查询父节点有几个,
难点:建模的时候应该吧上下联通的和左右联通的标记一下,只要他们和上下左右的都能连通,就把他们并到一个集合里面,我是只判断下和右即可,
源代码:
#include<stdio.h> #include<string.h> int up[8], down[8], right[8], left[8]; int par[2504]; char map[54][54]; char mp1[100][100]; char mp2[100][100]; void init() { up[0] = 'A'; up[1] = 'B'; up[2] = 'E'; up[3] = 'G'; up[4] = 'H'; up[5] = 'J'; up[6] = 'K'; down[0] = 'C'; down[1] = 'D'; down[2] = 'E'; down[3] = 'H'; down[4] = 'I'; down[5] = 'J'; down[6] = 'K'; left[0] = 'A'; left[1] = 'C'; left[2] = 'F'; left[3] = 'G'; left[4] = 'H'; left[5] = 'I'; left[6] = 'K'; right[0] = 'B'; right[1] = 'D'; right[2] = 'F'; right[3] = 'G'; right[4] = 'I'; right[5] = 'J'; right[6] = 'K'; memset(mp1, 0, sizeof(mp1)); memset(mp2, 0, sizeof(mp2)); for (int i = 0; i <= 6; i++){ for (int j = 0; j <= 6; j++){ mp1[down[i]][up[j]] = 1; mp2[right[i]][left[j]] = 1; } } } int findset(int x){ if(x!=par[x]) par[x]=findset(par[x]); return par[x]; } void unite(int x,int y){ int px=findset(x); int py=findset(y); if(px!=py) par[py]=px; } int main() { int M, N; init(); while (scanf("%d%d", &M, &N) != EOF){ if (M == -1 && N == -1) break; for (int i = 0; i < M; i++){ scanf("%s", map[i]); } for (int i = 0; i <= M * N; i++){ par[i] = i; } for (int i = 0; i < M; i++){ for (int j = 0; j < N; j++){ if (j < N - 1 && mp2[map[i][j]][map[i][j+1]] == 1){ int t1 = i * N + j; int t2 = i * N + j + 1; unite(t1, t2); } if (i < M - 1 && mp1[map[i][j]][map[i + 1][j]] == 1){ int t1 = i * N + j; int t2 = (i + 1) * N + j; unite(t1, t2); } } } int ans = 0; for (int i = 0; i < M * N; i++){ if (par[i] == i){ ans++; } } printf("%d\n", ans); } return 0; }