题目链接:http://cogs.pro:8081/cogs/problem/problem.php?pid=pNyNQiqge
思路:
基础是并查集,将两个相邻的岛算作一个集合,每次若合并成功,则N--,最终得到的即为答案。
先按读入岛的x1进行升序排序,然后遍历每个节点,对于节点i,取之后的j,并且要求 j 的x1 <= i 的x2 + 1,之后进行判断
判断内容为:
如果i的y2小于j的y1 - 1,或者i的y1大于等于j的y2 + 1,即两块陆地在x坐标上未有交集且不相邻,则return false。
如果i的x2 + 1 == j的x1:
此时,如果i的y2 + 1 == j的y1 说明两块陆地只有一个点相交,return false
否则,就return true
代码如下:
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstdio> #include <algorithm> #define MAXN 10010 using namespace std; int n, ct; int pre[MAXN]; struct Land { int x1, y1, x2, y2; bool operator<(const Land& a)const { if (x1 != a.x1) return x1 < a.x1; return y1 < a.y1; } }land[MAXN]; int find(int x) { if (x == pre[x]) return x; return pre[x] = find(pre[x]); } int Union(int x, int y) { int xPre = find(x); int yPre = find(y); if (xPre == yPre) return 0; else { pre[xPre] = yPre; return 1; } } int judge(const Land& a, const Land& b) { if (a.y1 - 1 > b.y2 || a.y2 + 1 < b.y1) return 0; if (a.x2 + 1 == b.x1) { if (a.y1 - 1 == b.y2 || a.y2 + 1 == b.y1) return 0; else return 1; } else return 1; } int main() { freopen("jx.in", "r", stdin); freopen("jx.out", "w", stdout); scanf("%d", &n); ct = n; for (int i = 0; i < n; i++) { scanf("%d %d %d %d", &land[i].x1, &land[i].y1, &land[i].x2, &land[i].y2); pre[i] = i; } sort(land, land + n); for (int i = 0; i < n; i++) { for(int j = i + 1; j < n && land[j].x1 <= land[i].x2 + 1; j++) if (judge(land[i], land[j]) && Union(i, j)) { ct--; } } printf("%d\n", ct); return 0; }