hdu3231 (三重拓扑排序)

这道题算是我拓扑排序入门的收棺题了,卡了我好几天,期间分别犯了超时,内存溢出,理解WA,细节WA,格式WA……

题目的意思大概是在一个三维坐标系中,有一大堆矩形,这些矩形的每条棱都与坐标轴平行。

这些矩形有4种情况——

1. 有重合部分(I a b) 表示a与b重合;

2. a的x坐标大于b的x坐标(X a b),表示a的最大的x坐标大于b的最小的x坐标;

3. (Y a b)y坐标,同上;

4. (Z a b)z坐标,同上;

也就是说,我们可以把每个矩形ai按照三个方向分解,分别为——平行于xoy平面的ai的上平面a01和ai的下平面a02,平行于xoz平面的ai的左平面a11和ai的右平面a12,平行于yoz平面的ai的前平面a21和ai的后平面a22。

假设有(I a b),那么表示a01 < b02, a02 < b01;

假设有(X a b),那么表示a02 < b01;

假设有(Y a b),那么表示a12 < b11;

假设有(Y a b),那么表示a22 < b21;

同时,每个矩形自身有特点:a01 < a02, a11<aa2, a21 < a22;

然后我们就分别获得了关于所有矩形的三个平面上的拓扑关系,然后分别对三个平面进行拓扑排序,如果有一组不满足,那么就输出不可能。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 using namespace std;
  5
  6 const int N = 1010;
  7 const int M = 100010;
  8
  9 struct Node
 10 {
 11     int val[3];
 12     int ds[3];
 13 }s[N<<2];   //保存每个平面的坐标值和深度(前面有几个平面)
 14
 15 struct node
 16 {
 17     int to;
 18     int next;
 19 }eage[3][M<<1];     //每组平面之间的关系
 20
 21 int n, m;
 22 int a, b;
 23 char ch[2];
 24 int head[3][M<<1];
 25 int tm = 1;
 26 int k[3];
 27
 28 bool tsort(int x)
 29 {
 30     queue<int> que;
 31
 32     int sum = 0;
 33     for(int i = 2; i <= 2*n+1; i++)
 34     {
 35         if(s[i].ds[x] == 0)
 36         {
 37             que.push(i);
 38             s[i].val[x] = 0;
 39         }
 40     }
 41     while(!que.empty())
 42     {
 43         int p = que.front();
 44         que.pop();
 45         s[p].ds[x]--;
 46         sum++;
 47
 48         for(int i = head[x][p]; i != -1; i = eage[x][i].next)
 49         {
 50             int v = eage[x][i].to;
 51             s[v].ds[x]--;
 52             if(s[v].ds[x] == 0)
 53             {
 54                 que.push(v);
 55                 s[v].val[x] = s[p].val[x]+1;
 56             }
 57         }
 58     }
 59     if(sum == 2*n) return 1;
 60     return 0;
 61 }
 62
 63 void get(int x, int a, int b)
 64 {
 65     eage[x][k[x]].to = b;
 66     eage[x][k[x]].next = head[x][a];
 67     head[x][a] = k[x]++;
 68     s[b].ds[x]++;
 69 }
 70
 71 int main()
 72 {
 73     //freopen("test.txt", "r", stdin);
 74     while(~scanf("%d%d", &n, &m) && (n+m))
 75     {
 76         memset(k, 0, sizeof(k));
 77         memset(head, -1, sizeof(head));
 78         memset(s, 0, sizeof(s));
 79
 80         while(m--)
 81         {
 82             scanf("%s%d%d", ch, &a, &b);
 83             if(ch[0] == ‘I‘)
 84             {
 85                 for(int i = 0; i < 3; i++)
 86                 {
 87                     get(i, 2*a, 2*b+1);
 88                     get(i, 2*b, 2*a+1);
 89                 }
 90             }
 91             else get(ch[0]-‘X‘, 2*a+1, 2*b);
 92         }
 93         for(int i = 1; i <= n; i++)
 94             for(int j = 0; j < 3; j++) get(j, 2*i, 2*i+1);
 95
 96         printf("Case %d: ", tm++);
 97         bool p = 0;
 98         for(int i = 0; i < 3; i++)
 99         {
100             if(!tsort(i))
101             {
102                 printf("IMPOSSIBLE\n\n");
103                 p = 1;
104                 break;
105             }
106
107         }
108         if(p) continue;
109
110         printf("POSSIBLE\n");
111         for(int i = 2; i <= 2*n+1; i++)
112         {
113             for(int j = 0; j < 3; j++)
114             {
115                 printf("%d", s[i].val[j]);
116                 if(i%2 == 0|| j < 2) printf(" ");
117                 else printf("\n");
118             }
119         }
120         printf("\n");
121     }
122     return 0;
123 }

代码姿势和大神比还是很挫……需要继续努力!

时间: 2024-10-03 19:45:23

hdu3231 (三重拓扑排序)的相关文章

HDU3231拓扑排序

Box Relations Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1334    Accepted Submission(s): 540Special Judge Problem Description There are n boxes C1, C2, ..., Cn in 3D space. The edges of the

拓扑排序讲解

在这里我们要说的拓扑排序是有前提的 我们在这里说的拓扑排序是基于有向无环图的!!!. (⊙o⊙)…我所说的有向无环图都知道是什么东西吧.. 如果不知道,我们下面先来来说说什么是有向无环图. 所谓有向无环图,顾名思义是不存在环的有向图(至于有向图是什么不知道的在前面我们有一个图论讲解上都有). 点的入度:以这个点为结束点的边数. 点的出度:以这个点为出发点的边的条数. 拓扑序就是对于一个节点的一个排列,使得(u,v)属于E,那么u一定出现在v的前面.然而拓扑排序就是一个用来求拓扑序的东西. 对于左

CSU 1804: 有向无环图(拓扑排序)

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 题意:…… 思路:对于某条路径,在遍历到某个点的时候,之前遍历过的点都可以到达它,因此在这个时候对答案的贡献就是∑(a1 + a2 + a3 + ... + ai) * bv,其中a是之前遍历到的点,v是当前遍历的点. 这样想之后就很简单了.类似于前缀和,每次遍历到一个v点,就把a[u]加给a[v],然后像平时的拓扑排序做就行了. 1 #include <bits/stdc++.h>

7-9-有向图无环拓扑排序-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第7章  图 - 有向无环图拓扑排序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.SequenceStack.c.ALGraph.c    

hihoCoder 1175:拓扑排序二

题目链接: http://hihocoder.com/problemset/problem/1175 题目难度:一星级(简单题) 今天闲来无事,决定刷一道水题.结果发现这道水题居然把我卡了将近一个钟头. 最后终于调通了.总结起来,原因只有一个:不够仔细. 思路不用细说了,就是拓扑排序的简单应用.然而,一些不起眼的细节才是让你掉坑里的真正原因. 猜猜哪儿可能出bug? // A simple problem, but you can't be too careful with it. #inclu

hdu1285(拓扑排序)

这道题要求没有输赢关系的两个元素必须按照升序输出,有输赢关系的,赢得在输的前面,所以用队列或者栈来降低时间复杂度的优化过的拓扑排序会出错. 比如这组输入 5 3 1 2 2 3 4 5 至少我写的两种拓扑排序都wa了.但是不用队列或者栈来优化的话, 1.每次都从头至尾扫描一遍,找到一个没标记过的节点, 2.将它标记 3.然后删除从它出来的每条边. 重复这三个操作,加标记的次序,就是题目要的答案. 下面的代码中用到了队列,但只是用来保存答案而已.并没有用它优化的意思. #include <iost

uva 10305 Ordering Tasks(拓扑排序)

拓扑排序,不用判断是否有环,dfs挺简单的 代码: #include<stdio.h> #include<string.h> #include<stdlib.h> int map[105][105]; int visit[105]; int c[105]; int n,m,t; void dfs(int x) { visit[x] = 1; for(int i=1; i<=n; i++) { if(!visit[i]&&map[i][x]==1)

NOJ 2015年陕西省程序设计竞赛网络预赛(正式赛)(忙碌的选课系统-拓扑排序注意重边)

D - 忙碌的选课系统 Time Limit: 10000 ms        Memory Limit: 65536 KB Submit Description 每学期末,都是万众瞩目的选课时间,由于人数过多,某学校的服务器常常被无数的学生挤的爆掉,这是,教务系统大人说,你们选个课都这么慢,居然还怪我们.于是,每次教务系统都会在服务器快要瘫痪前关闭它.在无数学生的强烈抗议下,教务系统妥协了,再给每个人一次机会,但他让我们用最快的方式决定该选的课程,选上后就退出. 这让大一学渣狗犯了难,在新的选

POJ1420 Spreadsheet(拓扑排序)注意的是超内存

Spreadsheet Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 617   Accepted: 290 Description In 1979, Dan Bricklin and Bob Frankston wrote VisiCalc, the first spreadsheet application. It became a huge success and, at that time, was the ki