您的位置:首页 > 其它

hdu3231 拓扑序

2015-09-09 16:36 267 查看
题意:在空间内有多个长方体,有一系列关系,分别是 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=1005*2;
const int maxm=110005;

int id[3][maxn],n;
int num[3][maxn];
int head[3][maxn],point[3][maxm],nxt[3][maxm],size[3];
char s[5];

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=1;i<=2*n;++i)if(!id[c][i])q.push(i);
int cnt=0;
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==2*n)return 1;
return 0;
}

int main(){
int cnt=0,m;
while(scanf("%d%d",&n,&m)!=EOF&&n+m){
memset(head,-1,sizeof(head));
memset(size,0,sizeof(size));
memset(id,0,sizeof(id));
for(int i=1;i<=n;++i){
add(2*i-1,2*i,0);
add(2*i-1,2*i,1);
add(2*i-1,2*i,2);
}
while(m--){
int a,b;
scanf("%s%d%d",s,&a,&b);
if(s[0]=='X')add(2*a,2*b-1,0);
else if(s[0]=='Y')add(2*a,2*b-1,1);
else if(s[0]=='Z')add(2*a,2*b-1,2);
else if(s[0]=='I'){
add(2*a-1,2*b,0);
add(2*a-1,2*b,1);
add(2*a-1,2*b,2);
add(2*b-1,2*a,0);
add(2*b-1,2*a,1);
add(2*b-1,2*a,2);
}
}
printf("Case %d: ",++cnt);
if(!topo(0))printf("IMPOSSIBLE\n");
else if(!topo(1))printf("IMPOSSIBLE\n");
else if(!topo(2))printf("IMPOSSIBLE\n");
else{
printf("POSSIBLE\n");
for(int i=1;i<=n;++i){
printf("%d %d %d %d %d %d\n",num[0][2*i-1],num[1][2*i-1],num[2][2*i-1],num[0][2*i],num[1][2*i],num[2][2*i]);
}
}
printf("\n");
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: