并查集_HDU_2235

藏的很深的并查集,先按每个点的高度排序,从最小并查起
每次访问点的四边,看是否有以当前高度为边的可以放水的
然后还要标记点在哪些情况下是是段木板,例如
4 4
4 4 4 4
4 0 1 4
4 2 3 4
4 4 4 4
按照高度排序之后,从小开始,我们先读到0的位置,那么0的四周没有比
0小的,不存在以它为边可以放水的,访问1时,存在0可以放水,放完水之后,0并到1,之后访问2,此时有0,而0并到1,整块已经考虑,那么久是两个地方可以放水。。。。
总之,大概思路就是水从最低处开始蔓延,逐渐淹没旁边的,直到最后蔓延出界(数组四边)

#include
#include
#include
#include
const int maxn = 505;
using namespace std;
int n,m;
struct Point
{
    int location;
    int high;
}dp[maxn*maxn];
struct node
{
    int num;
    int H;
}map[maxn][maxn];
int fx[] = {-1,1,0,0};
int fy[] = {0,0,-1,1};
int cmp(const void *a, const void *b)
{
    Point *c = (Point*)a;
    Point *d = (Point*)b;
    if(c->high == d->high)
        return c->location - d->location;
    return c->high - d->high;
}
int par[maxn*maxn],vis[maxn][maxn];
int Find(int x)
{
    if(par[x] == x)
        return x;
    par[x] = Find(par[x]);
    return par[x];
}
int main()
{
    int t;
    __int64 ans;
    scanf("%d",&t);
    while(t--)
    {
        ans = 0;
        scanf("%d%d",&n,&m);
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                scanf("%d",&map[i][j].H);
                map[i][j].num = 1;
                dp[i*m+j].high = map[i][j].H;
                dp[i*m+j].location = i*m+j;
                par[i*m+j] = i*m+j;
                vis[i][j] = 0;
            }
        }
        qsort(dp,n*m,sizeof(dp[0]),cmp);
        for(int i = 0; i < n*m; i++)
        {
            bool flag = false;
            int x = dp[i].location/m;
            int y = dp[i].location%m;
            vis[x][y] = 1;
            for(int j = 0; j < 4; j++)
            {
                int xi = x+fx[j];
                int yi = y+fy[j];
                if(xi<0||xi>=n||yi<0||yi>=m)
                {
                    flag = true;
                    continue;
                }
                int fa = Find(xi*m+yi);
                if(fa == dp[i].location)continue;
                xi = fa/m;
                yi = fa%m;
                if(vis[xi][yi]==1&&map[xi][yi].num != 0)
                {
                    ans += (map[x][y].H-map[xi][yi].H)*map[xi][yi].num;
                    par[fa] = dp[i].location;
                    map[x][y].num += map[xi][yi].num;
                }
                else if(map[xi][yi].num == 0)
                {
                    flag = true;
                    par[fa] = dp[i].location;
                }
            }
            if(flag)
                map[x][y].num = 0;
        }
        cout<return 0;
}

你可能感兴趣的:(ACM水题刷耍)