给你一个n*n的矩阵,每个格子的数代表给格子的海拔,求下一之后的积水是多少。(n<=1000)
思路:思路还是很巧妙的,维护并查集,排序以后从小到大枚举高度,然后看四周有没有之前已经访问过的或者已经flow的,就算是已经漏水的,漏水的话,这个格子也会露水,否则吧当前高度作为父亲,排序的作业是英文漏水只可能从低的地方漏水,不可能从高的地方漏水。
代码:
#include<algorithm>
#include<iostream>
#include<stdio.h>
#include<string.h>
//using namespace std;
const int maxn=1010;
int f[maxn*maxn];
int ix[5]= {0,0,1,-1};
int iy[5]= {-1,1,0,0};
int n;
inline int get(int v)
{
return f[v]==v?v:f[v]=get(f[v]);
}
inline void Merge(int v,int u)
{
int t1 = get(v);
int t2 = get(u);
f[t1] = t2;
return;
}
struct node
{
int x,y;
int high,num;
bool flow,vi;
} N[maxn*maxn];
int MAP[maxn*maxn];
inline int check(int x,int y)
{
if(x==0||x==n-1||y==0||y==n-1)
return 1;
return 0;
}
using ll=long long ;
char buf[16 * 1024 * 1024 + 5]; // 10 MiB Buffer
int curpos = 0, iseof;
int nextInt()
{
int ret = 0;
if (iseof)
return 0;
while (!('0' <= buf[curpos] && buf[curpos] <= '9'))
{
if (buf[curpos] == 0)
{
if (fgets(buf, 16 * 1024 * 1024, stdin) == NULL)
iseof = true;
curpos = 0;
continue;
}
curpos++;
}
int flg = 0;
if (curpos && buf[curpos - 1] == '-')
flg = -1;
else
flg = 1;
while ('0' <= buf[curpos] && buf[curpos] <= '9')
{
ret = ret * 10 + (buf[curpos] - '0');
curpos++;
}
return ret * flg;
}
int main()
{
// std::ios::sync_with_stdio(false);
// scanf("%d",&n);
n=nextInt() ;
int num=1;
memset(f,0,sizeof(f));
memset(MAP,0,sizeof(MAP));
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
int x;
x=nextInt() ;
// scanf("%d",&x);
f[num]=num;
N[num].x=i;
N[num].y=j;
N[num].num=num;
N[num].high=x;
N[num].flow=false;
N[num].vi=false;
num++;
}
std::sort(N+1,N+num,[=](node a,node b)
{
return a.high<b.high;
});
// for(int i=1; i<num; i++)
// std::cout<<N[i].num<<" "<<N[i].high<<'\n';
for(int i=1; i<num; i++)
MAP[N[i].num]=i;
for(int i=1; i<num; i++)
{
if(check(N[i].x,N[i].y))
N[i].flow=true;
N[i].vi=true;
for(int j=0; j<4; j++)
{
int xx=N[i].x+ix[j];
int yy=N[i].y+iy[j];
if(xx<0||xx>=n||yy<0||yy>=n)
continue;
int ns=n*xx+yy+1;
int root=get(ns);
if(N[MAP[root]].flow)
N[i].flow=1;
else if(N[MAP[ns]].vi)
Merge(N[MAP[ns]].num,N[i].num);
}
}
ll sum=0;
for(int i=1; i<num; i++)
{
// std::cout<<get(N[i].num)<<" "<<N[i].num<<'\n';
sum+=N[MAP[get(N[i].num)]].high-N[i].high;
}
printf("%lld\n",sum);
// std::cout<<sum<<'\n';
}
/*
4
3 4 5 6
4 1 2 7
5 1 2 8
6 7 8 9
3
2 3 4
4 1 2
2 2 2
*/
来源:CSDN
作者:dongdongdong122
链接:https://blog.csdn.net/dongdongdong122/article/details/104165807