1. 程式人生 > >BZOJ1104: [POI2007]洪水pow

BZOJ1104: [POI2007]洪水pow

define none 指定 所有 位置 iostream ID gif tdi

$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\n",ans); 60 return 0; 61 }
View Code

BZOJ1104: [POI2007]洪水pow