6525. [2020.4.1] simulation Valleys

topic

Give you a map, the number on each square represents its height.
The definition of "valley" is: a height greater than its surroundings, and no holes in the block.
A hole is defined as: after the deleted block, the remaining birds can not communicate with the point of intersection to form a block.
Find all the valley and the size of the.


Correct

Thinking course, there is no, it is not good to start thinking of this question.

If we do not consider the cave how to do it. This is a primary question: with disjoint-set to maintain the block. The height of the small to large, when a point operation, it is adjacent, and a height less than or equal its point at which it is merging block. Incidentally, remember what number of points, you can find the answer.

Our problem now is how to quickly determine whether a block with holes.
Many methods seem, here introduce plane Tuou La formula:
referred to \ (V \) in dots, (E \) \ is the number of edges, \ (F. \) Is the number of regions, the \ (V + F = E + 2 \)

Consider a legitimate valley. (Length of the first side block calculate how many small squares \ (1 \) square dot formation communicate with each other), referred to as \ (S \)
if the valley valid, then the \ (F = S + 1 \ ) . This latter \ (1 \) is the outermost of the block.
If you are not legitimate, this equation is not established.

So we only need to maintain \ (V \) , \ (E \) , \ (S \) . For (S \) \ maintenance, noticed a small square grid of the new generation will certainly include the current point, enumerate what you can easily maintain.


Code

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 800
#define ll long long
int n,m;
int id[N][N],h[N*N];
bool vis[N*N];
#define at(x,y) h[id[x][y]]
struct DOT{int x,y;} d[N*N];
inline bool cmpd(DOT a,DOT b){return at(a.x,a.y)<at(b.x,b.y);}
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
int fa[N*N],V[N*N],E[N*N],sq[N*N];
int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
#define in(x,y,z) ((1<=x && x<=n && 1<=y && y<=n) && getfa(id[x][y])==z)
int main(){
//	freopen("in.txt","r",stdin);
	freopen("valleys.in","r",stdin);
	freopen("valleys.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;++i)
		for (int j=1;j<=n;++j){
			id[i][j]=++m;
			d[m]={i,j};
			scanf("%d",&h[m]);
		}
	sort(d+1,d+m+1,cmpd);
	for (int i=1;i<=m;++i)
		fa[i]=i,V[i]=1,E[i]=0,sq[i]=0;
	ll ans=0;
	for (int i=1;i<=m;++i){
		int x=d[i].x,y=d[i].y,z=id[x][y];
		vis[z]=1;
		for (int j=0;j<4;++j){
			int tx=x+dx[j],ty=y+dy[j],tz=id[tx][ty];
			if (tx<1 || tx>n || ty<1 || ty>n || !vis[tz])
				continue;
			int r=getfa(tz);
			if (r!=z){
				fa[r]=z;
				V[z]+=V[r];
				E[z]+=E[r];
				sq[z]+=sq[r];
			}
			E[z]++;
		}
		for (int j=0;j<4;++j){
			int k=(j+1)%4;
			if (in(x+dx[j],y+dy[j],z) && in(x+dx[k],y+dy[k],z) && in(x+dx[j]+dx[k],y+dy[j]+dy[k],z))
				sq[z]++;
		}
		if (i==m || at(x,y)!=at(d[i+1].x,d[i+1].y))
			ans+=(E[z]-V[z]+2-sq[z]==1?V[z]:0);
	}
	printf("%lld\n",ans);
	return 0;
}

to sum up

Those weird formula theorems, some of it true that accumulated ......

Guess you like

Origin www.cnblogs.com/jz-597/p/12623307.html