Hdu3231【拓扑排序】

</pre><pre name="code" class="cpp">/*Box Relations
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1155    Accepted Submission(s): 440
Special Judge

Problem Description
There are n boxes C1, C2, ..., Cn in 3D space. The edges of the boxes are parallel to the x, y or z-axis. We provide some relations of the boxes, and your task is to construct a set of boxes satisfying all these relations.

There are four kinds of relations (1 <= i,j <= n, i is different from j):

I i j: The intersection volume of Ci and Cj is positive.

X i j: The intersection volume is zero, and any point inside Ci has smaller x-coordinate than any point inside Cj.

Y i j: The intersection volume is zero, and any point inside Ci has smaller y-coordinate than any point inside Cj.

Z i j: The intersection volume is zero, and any point inside Ci has smaller z-coordinate than any point inside Cj.
.
 

Input
There will be at most 30 test cases. Each case begins with a line containing two integers n (1 <= n <= 1,000) and R (0 <= R <= 100,000), the number of boxes and the number of relations. Each of the following R lines describes a relation, written in the format above. The last test case is followed by n=R=0, which should not be processed.
 

Output
For each test case, print the case number and either the word POSSIBLE or IMPOSSIBLE. If it's possible to construct the set of boxes, the i-th line of the following n lines contains six integers x1, y1, z1, x2, y2, z2, that means the i-th box is the set of points (x,y,z) satisfying x1 <= x <= x2, y1 <= y <= y2, z1 <= z <= z2. The absolute values of x1, y1, z1, x2, y2, z2 should not exceed 1,000,000.

Print a blank line after the output of each test case.
 

Sample Input
3 2
I 1 2
X 2 3
3 3
Z 1 2
Z 2 3
Z 3 1
1 0
0 0
 

Sample Output
Case 1: POSSIBLE
0 0 0 2 2 2
1 1 1 3 3 3
8 8 8 9 9 9

Case 2: IMPOSSIBLE

Case 3: POSSIBLE
0 0 0 1 1 1
 

Source
2009 Asia Wuhan Regional Contest Hosted by Wuhan University 
 

Recommend
chenrui
*/ 
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int n, m, nn;
//每一个面都看作一个点 
struct Point
{
	int next[200], ans, in;
}P[3][2016];
//添加偏序关系 
void add_point(int d, int x, int y)
{
	P[d][y].in++;
	int temp = ++P[d][x].next[0];
	P[d][x].next[temp] = y;
}

int que[2016];

bool top(int d)
{
	que[0] =  0;
	for(int i = 1; i <= nn; ++i)
	if(P[d][i].in == 0)
	que[++que[0]] = i;
	int num = 1, num2;
	while(num <= que[0])
	{
		//入度为0的集合 
		num2 = que[0];
		for(int i = num; i <= num2; ++i)
		{
			for(int j = 1; j <= P[d][ que[i] ].next[0]; ++j)
			{
				//que[i] --> next[j]
				int temp = P[d][ que[i] ].next[j];
				P[d][temp].in--;
				if(P[d][temp].in == 0)
				{
					que[++que[0]] = temp;
					P[d][temp].ans = P[d][ que[i] ].ans+1;
				}
			}
		}
		num = num2+1;
	}
	if(que[0] == nn)
	return true;
	else
	return false;
}
int main()
{
	int i, j, k, cas = 1;
	char ch;
	while(scanf("%d%d", &n, &m) != EOF && (n || m) )
	{
		memset(P, 0, sizeof(P));
		getchar();
		nn = n<<1;
		//初始化偏序   将长方体左面标记为序号i右面标记为i+n
		for(i = 1; i <= n; ++i)
		for(j = 0; j < 3; ++j)
		add_point(j, i, i+n);
		//题目给出的偏序 
		for(i = 0; i < m; ++i)
		{
			scanf("%c %d %d", &ch, &j, &k);
			getchar();
			//交叉时得出的偏序 
			if(ch == 'I')
			{
				add_point(0, j, k+n);
				add_point(0, k, j+n);
				add_point(1, j, k+n);
				add_point(1, k, j+n);
				add_point(2, j, k+n);
				add_point(2, k, j+n);
			}
			else
			{
				int temp = ch - 'X';
				add_point(temp, j+n, k);
			}
		}
		printf("Case %d: ", cas++); 
		//对每一个维度的面进行拓扑排序
		if(!top(0) || !top(1) || !top(2))
		printf("IMPOSSIBLE\n");
		else
		{
			printf("POSSIBLE\n");
			for(i = 1; i <= n; ++i)
			printf("%d %d %d %d %d %d\n", P[0][i].ans, P[1][i].ans, P[2][i].ans, P[0][i+n].ans, P[1][i+n].ans, P[2][i+n].ans);
		}
		printf("\n");
	}
	return 0;
} 

题意:有n个长方体,长方体的每条边都与座标轴平行,现在长方体之间有四种关系,一种是交叉另一种是没有交叉,但是前一个长方体中的任何一个点的x(y,z)座标都小于第二个长方体。求这些长方体的座标(多种可能,输出一个即可)。

思路:对于长方体交叉的情况,可以知道2个长方体平行的四个面之间有一种关系,x1,x2为其中一个长方体的2个平行面的座标,x3,x4为另一个,x1<x4,x3<x2,即每一个长方体的左面一定在另一个长方体的右面的左边,对于其他 三种关系则只有一种联系,即左边的长方体的右面在右边的长方体的左面的左边。我们把每个面所对应的座标作为一个点,然后要对座标轴的每一维度分别进行拓扑排序,只要三个维度的拓扑都能完成,则可能。在拓扑的时候根据入度为0的前后关系,把后一个点的座标在前一个点的座标的前提下+1即可。最后输出每个长方体的座标即可。(这里还有长方体本身的2个面之间座标默认的偏序,即x1<x2,作为初始化的偏序关系)。

体会:这题难在分析题意以及拓扑排序的运用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章