暑假集训中期测试 Problem D: 装箱问题2 (并查集)

Description

有很多个棱长为1的正方体货物整齐地堆在一堆。不过有一些是悬空的, 大概是粘上去的吧。。。

给出这些货物的相邻关系,求最小的长方体(或正方体)能装下这些货物的集装箱的体积,(集装箱棱长方向与这些正方体三个棱方向平行)。

Input

每组数据第一行一个n,表示有n个货物。1 <= n <= 1000

接下来n行每行6个数,第i行表示以棱方向为轴的x轴正负、y轴正负、z轴正负方向与第i个货物相邻的货物编号(i为1~n),0表示无该位置信息。

Output

如果描述出现矛盾或者无法确定货物是堆在一起的,输出"What?",否则输出集装箱体积。

Sample Input

3
0 0 0 0 3 2
0 0 0 0 1 0
0 0 0 0 0 1

Sample Output

3
 
View Code
#include <stdio.h>

#define N 1005

#define MIN(a,b) ((a)<(b)?(a):(b))

#define MAX(a,b) ((a)>(b)?(a):(b))

#define INF 0x3fffffff

int x[N],y[N],z[N];

int p[N];

int n;

void make_set()

{

    for(int i=1;i<=n;i++)   p[i]=i,x[i]=y[i]=z[i]=0;

}

int find_set(int i)

{

    int pi=p[i];

    if(i^p[i])  p[i]=find_set(p[i]);

    if(pi^p[i])

    {

        x[i]+=x[pi];

        y[i]+=y[pi];

        z[i]+=z[pi];

    }

    return p[i];

}

void union_set(int i,int j,int dir,int d)

{

    int pi,pj;

    pi=find_set(i);

    pj=find_set(j);

    p[pj]=pi;

    //dir为0 表示 i与j在x方向上相邻,d=1表示j在i右边

    if(dir==0)

    {

        x[pj]=x[i]-x[j]+d;

        y[pj]=y[i]-y[j];

        z[pj]=z[i]-z[j];

    }

    else if(dir==1)

    {

        x[pj]=x[i]-x[j];

        y[pj]=y[i]-y[j]+d;

        z[pj]=z[i]-z[j];

    }

    else

    {

        x[pj]=x[i]-x[j];

        y[pj]=y[i]-y[j];

        z[pj]=z[i]-z[j]+d;

    }

}

int main()

{

    int i,j;

    bool wa;

    while(~scanf("%d",&n))

    {

        make_set();

        wa=false;

        for(i=1;i<=n;i++)

        {

            for(int dir=0;dir<3;dir++)

            {

                for(int d=1;d>=-1;d-=2)

                {

                    scanf("%d",&j);

                    if(j==0)    continue;

                    if(find_set(i)^find_set(j)) union_set(i,j,dir,d);

                    else

                    {

                        if(dir==0 && !(y[i]==y[j]&&z[i]==z[j]&&d==x[j]-x[i]))  wa=true;

                        if(dir==1 && !(x[i]==x[j]&&z[i]==z[j]&&d==y[j]-y[i]))  wa=true;

                        if(dir==2 && !(y[i]==y[j]&&x[i]==x[j]&&d==z[j]-z[i]))  wa=true;

                    }

                }

            }

        }

        for(i=2;!wa && i<=n;i++)   if(find_set(i)!=find_set(1))    wa=true;

        int minx=INF,maxx=-INF;

        int miny=INF,maxy=-INF;

        int minz=INF,maxz=-INF;

        if(wa)  puts("What?");

        else

        {

            for(int i=1;i<=n;i++)

            {

                minx=MIN(minx,x[i]);    maxx=MAX(maxx,x[i]);

                miny=MIN(miny,y[i]);    maxy=MAX(maxy,y[i]);

                minz=MIN(minz,z[i]);    maxz=MAX(maxz,z[i]);

            }

            printf("%d\n",(maxx-minx+1)*(maxy-miny+1)*(maxz-minz+1));

        }

    }

    return 0;

}

 

你可能感兴趣的:(并查集)