版权声明:xgc原创文章,未经允许不得转载。 https://blog.csdn.net/xgc_woker/article/details/82905412
Description
给你n*m的图,每个点有一个海拔,在较低的点放置吸水器能吸到比较高的点,有一些点是必须要吸的,问你最少需要多少吸水器。
Sample Input
6 9
-2 -2 -1 -1 -2 -2 -2 -12 -3
-2 1 -1 2 -8 -12 2 -12 -12
-5 3 1 1 -12 4 -6 2 -2
-5 -2 -2 2 -12 -3 4 -3 -1
-5 -6 -2 2 -12 5 6 2 -1
-4 -8 -8 -10 -12 -8 -6 -6 -4
Sample Output
2
将权值从小到大排序,对于每一个点去四周寻找已经染过的点。
然后每染完一个权值就判断一下,他所处的集合中是否有吸水器。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
int read() {
int s = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * f;
}
struct node {
int x, y, c;
} a[1100000];
bool v[1100000], ned[1100000];
int n, m, w[1100000], fa[1100000];
bool cmp(node a, node b) {return a.c < b.c;}
int findfa(int x) {
if(fa[x] != x) fa[x] = findfa(fa[x]);
return fa[x];
}
void findw(int x, int y) {
int u = (x - 1) * m + y;
for(int k = 0; k < 4; k++) {
int nx = x + dx[k], ny = y + dy[k];
if(nx <= 0 || ny <= 0 || nx > n || ny > m) continue;
int y = (nx - 1) * m + ny;
if(v[y]) {
int fy = findfa(y), fu = findfa(u);
fa[fu] = fy; w[fy] |= w[fu];
}
}
}
int main() {
n = read(), m = read();
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) {
int x = (i - 1) * m + j;
a[x].x = i, a[x].y = j, a[x].c = read();
if(a[x].c < 0) a[x].c = abs(a[x].c), ned[x] = 1;
} sort(a + 1, a + n * m + 1, cmp);
int last = 1, ans = 0;
for(int i = 1; i <= n * m; i++) fa[i] = i;
for(int i = 1; i <= n * m; i++) {
findw(a[i].x, a[i].y);
if(a[i].c != a[i + 1].c) {
for(int j = last; j <= i; j++) {
int x = (a[j].x - 1) * m + a[j].y;
if(!ned[x]) {
int fx = findfa(x);
if(!w[fx])
ans++, w[fx] = 1;
}
} last = i + 1;
} v[(a[i].x - 1) * m + a[i].y] = 1;
} printf("%d\n", ans);
return 0;
}