题意:在空间内有多个长方体,有一系列关系,分别是 A 的所有点的 x 坐标都比 B 的所有点的 x 坐标小, A 的所有点的 y 坐标都比 B 的所有点的 y 坐标小, A 的所有点的 z 坐标都比 B 的所有点的 z 坐标小,或者是 A 和 B有体积相交。要求给出一个符合上述关系的各个长方体,输出它们主对角线上的两点坐标。
将每个长方体的 x 、 y 、 z 作为点。每个长方体有两个 x 点(x1为值小的点,x2为值大的点),两个 y 点,两个 z 点,他们之间的关系是用边表示, e(u,v) 表示 u 的值小于 v 的值,对于每个长方体的每一维的两点可以先建边,然后两长方体的坐标大小比较就是用坐标小的长方体的大值点(A 的 x2)向坐标大的长方体的小值点(B 的 x1)建边,而体积有相交则是两长方体的小值点向对方的大值点建边(A 的 x1 向 B 的 x2 ;B 的 x1 向 A 的 x2);然后对 x、y、z 分别求一遍拓扑序,再随意从小到大分配值就行了。
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=*;
const int maxm=; int id[][maxn],n;
int num[][maxn];
int head[][maxn],point[][maxm],nxt[][maxm],size[];
char s[]; void add(int a,int b,int c){
point[c][size[c]]=b;
nxt[c][size[c]]=head[c][a];
head[c][a]=size[c]++;
id[c][b]++;
} bool topo(int c){
queue<int>q;
for(int i=;i<=*n;++i)if(!id[c][i])q.push(i);
int cnt=;
while(!q.empty()){
int u=q.front();
q.pop();
num[c][u]=++cnt;
for(int i=head[c][u];~i;i=nxt[c][i]){
int j=point[c][i];
id[c][j]--;
if(!id[c][j])q.push(j);
}
}
if(cnt==*n)return ;
return ;
} int main(){
int cnt=,m;
while(scanf("%d%d",&n,&m)!=EOF&&n+m){
memset(head,-,sizeof(head));
memset(size,,sizeof(size));
memset(id,,sizeof(id));
for(int i=;i<=n;++i){
add(*i-,*i,);
add(*i-,*i,);
add(*i-,*i,);
}
while(m--){
int a,b;
scanf("%s%d%d",s,&a,&b);
if(s[]=='X')add(*a,*b-,);
else if(s[]=='Y')add(*a,*b-,);
else if(s[]=='Z')add(*a,*b-,);
else if(s[]=='I'){
add(*a-,*b,);
add(*a-,*b,);
add(*a-,*b,);
add(*b-,*a,);
add(*b-,*a,);
add(*b-,*a,);
}
}
printf("Case %d: ",++cnt);
if(!topo())printf("IMPOSSIBLE\n");
else if(!topo())printf("IMPOSSIBLE\n");
else if(!topo())printf("IMPOSSIBLE\n");
else{
printf("POSSIBLE\n");
for(int i=;i<=n;++i){
printf("%d %d %d %d %d %d\n",num[][*i-],num[][*i-],num[][*i-],num[][*i],num[][*i],num[][*i]);
}
}
printf("\n");
}
return ;
}