【Luogu3457】POW-The Flood(並查集)
阿新 • • 發佈:2018-02-24
logs truct inline stdin AI problem 每次 mark spa
所以在當前集合中一點要放一個抽水機,
那麽,給當前集合放一個抽水機,同時答案加一即可
【Luogu3457】POW-The Flood(並查集)
題面
洛谷
題解
我們知道,如果一個點和一個海拔不高於它的點相連
那麽連在那個點是更優的,所以考慮按照每個點的海拔排序
既然按照海拔排序,相鄰的海拔遞增的點可以放在同一個集合裏面討論
考慮使用並查集,每一個集合中只需要有一個抽水機即可
每次從海拔最低的點中選出一個點
將它和它周圍的海拔比當前海拔低的點直接鏈接在一起
同時,維護每個並查集是否存在抽水機
如果當前點是城市,並且所在的並查集中有抽水機了
顯然是不用再額外增加抽水機了
但是,如果當前點和周圍的點合並完之後,所在集合依然沒有抽水機
因為它所在的集合周圍的點海拔一定更高,不可能有抽水機
那麽,給當前集合放一個抽水機,同時答案加一即可
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 1010
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int n,m,g[MAX][MAX],bh[MAX][MAX];
struct Node{int id,x,y,w;}p[MAX*MAX];
bool operator<(Node a,Node b){return a.w<b.w;}
int f[MAX*MAX],pl[MAX*MAX],tot,ans;
int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
int d[4][2]={1,0,-1,0,0,1,0,-1};
void Merge(int u,int v)
{
pl[getf(v)]|=pl[getf(u)];
f[getf(u)]=getf(v);
}
int main()
{
freopen("pow.in","r",stdin);
freopen("pow.out","w",stdout);
n=read();m=read();
memset(g,-63,sizeof(g));
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
g[i][j]=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
p[++tot]=(Node){bh[i][j]=tot,i,j,abs(g[i][j])};
for(int i=1;i<=tot;++i)f[i]=i;
sort(&p[1],&p[tot+1]);
for(int i=1;i<=tot;++i)
{
int X=p[i].x,Y=p[i].y;
for(int k=0;k<4;++k)
{
int x=p[i].x+d[k][0],y=p[i].y+d[k][1];
if(abs(g[x][y])<=abs(g[X][Y]))Merge(getf(bh[x][y]),getf(bh[X][Y]));
}
if(abs(p[i+1].w)!=abs(p[i].w))
for(int j=i;abs(p[j].w)==abs(p[i].w);--j)
if(g[p[j].x][p[j].y]>0)
{
int u=getf(bh[p[j].x][p[j].y]);
if(!pl[u])pl[u]=1,++ans;
}
}
printf("%d\n",ans);
return 0;
}
【Luogu3457】POW-The Flood(並查集)