hdu3231 拓扑序

题意:在空间内有多个长方体,有一系列关系,分别是 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 分别求一遍拓扑序,再随意从小到大分配值就行了。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<queue>
 4 using namespace std;
 5 const int maxn=1005*2;
 6 const int maxm=110005;
 7 
 8 int id[3][maxn],n;
 9 int num[3][maxn];
10 int head[3][maxn],point[3][maxm],nxt[3][maxm],size[3];
11 char s[5];
12 
13 void add(int a,int b,int c){
14     point[c][size[c]]=b;
15     nxt[c][size[c]]=head[c][a];
16     head[c][a]=size[c]++;
17     id[c][b]++;
18 }
19 
20 bool topo(int c){
21     queue<int>q;
22     for(int i=1;i<=2*n;++i)if(!id[c][i])q.push(i);
23     int cnt=0;
24     while(!q.empty()){
25         int u=q.front();
26         q.pop();
27         num[c][u]=++cnt;
28         for(int i=head[c][u];~i;i=nxt[c][i]){
29             int j=point[c][i];
30             id[c][j]--;
31             if(!id[c][j])q.push(j);
32         }
33     }
34     if(cnt==2*n)return 1;
35     return 0;
36 }
37 
38 int main(){
39     int cnt=0,m;
40     while(scanf("%d%d",&n,&m)!=EOF&&n+m){
41         memset(head,-1,sizeof(head));
42         memset(size,0,sizeof(size));
43         memset(id,0,sizeof(id));
44         for(int i=1;i<=n;++i){
45             add(2*i-1,2*i,0);
46             add(2*i-1,2*i,1);
47             add(2*i-1,2*i,2);
48         }
49         while(m--){
50             int a,b;
51             scanf("%s%d%d",s,&a,&b);
52             if(s[0]=='X')add(2*a,2*b-1,0);
53             else if(s[0]=='Y')add(2*a,2*b-1,1);
54             else if(s[0]=='Z')add(2*a,2*b-1,2);
55             else if(s[0]=='I'){
56                 add(2*a-1,2*b,0);
57                 add(2*a-1,2*b,1);
58                 add(2*a-1,2*b,2);
59                 add(2*b-1,2*a,0);
60                 add(2*b-1,2*a,1);
61                 add(2*b-1,2*a,2);
62             }
63         }
64         printf("Case %d: ",++cnt);
65         if(!topo(0))printf("IMPOSSIBLE
");
66         else if(!topo(1))printf("IMPOSSIBLE
");
67         else if(!topo(2))printf("IMPOSSIBLE
");
68         else{
69             printf("POSSIBLE
");
70             for(int i=1;i<=n;++i){
71                 printf("%d %d %d %d %d %d
",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]);
72             }
73         }
74         printf("
");
75     }
76     return 0;
77 }
View Code
原文地址:https://www.cnblogs.com/cenariusxz/p/4795162.html