$n leq 1000,m leq 1000$,$n*m$的地图,每个格一个海拔,现在整个图都是水,问要多少个地方装抽水机能使所有指定位置被抽干(符合连通器原理)。
从小到大枚举每个指定格,然后有贡献的就是比当前指定格小的所有格,把他们用并查集搞起来。如果这样也不能使当前格被一个装了抽水机的并查集覆盖,就在自己并查集里装一个。
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 //#include<set> 5 #include<algorithm> 6 //#include<math.h> 7 //#include<iostream> 8 //#include<time.h> 9 using namespace std; 10 11 #define LL long long 12 int qread() 13 { 14 char c; int s=0,t=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (t=-1); 15 do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*t; 16 } 17 18 //Pay attention to read! 19 20 int n,m; 21 #define maxn 1011 22 int a[maxn][maxn],id[maxn][maxn],qx[maxn*maxn],qy[maxn*maxn],head,tail,ufs[maxn*maxn]; 23 bool vv[maxn][maxn],vis[maxn*maxn]; 24 int find(int x) {return x==ufs[x]?x:(ufs[x]=find(ufs[x]));} 25 void Union(int x,int y) {x=find(x),y=find(y); if (x==y) return; ufs[x]=y; vis[y]|=vis[x];} 26 27 int ans=0; 28 const int dx[]={0,0,1,-1},dy[]={1,-1,0,0}; 29 int Abs(int x) {return x>0?x:-x;} 30 31 struct Node{int x,y,v; bool operator < (const Node &b) const {return v<b.v;}}pp[maxn*maxn],qq[maxn*maxn]; 32 int lq; 33 34 int main() 35 { 36 n=qread(); m=qread(); 37 for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) 38 { 39 a[i][j]=qread(),id[i][j]=(i-1)*m+j,pp[id[i][j]]=(Node){i,j,Abs(a[i][j])}; 40 if (a[i][j]>0) qq[++lq]=(Node){i,j,a[i][j]}; 41 } 42 sort(pp+1,pp+1+n*m); 43 sort(qq+1,qq+1+lq); 44 for (int i=1;i<=n*m;i++) ufs[i]=i; 45 for (int i=1,j=1;i<=lq;i++) 46 { 47 for (;j<=n*m && pp[j].v<=qq[i].v;j++) 48 { 49 int nx=pp[j].x,ny=pp[j].y; 50 for (int k=0;k<4;k++) 51 { 52 int x=nx+dx[k],y=ny+dy[k]; 53 if (x<1 || x>n || y<1 || y>m) continue; 54 if (Abs(a[x][y])<=Abs(a[nx][ny])) Union(id[x][y],id[nx][ny]); 55 } 56 } 57 if (!vis[find(id[qq[i].x][qq[i].y])]) vis[ufs[id[qq[i].x][qq[i].y]]]=1,ans++; 58 } 59 printf("%d ",ans); 60 return 0; 61 }