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,作爲初始化的偏序關係)。

體會:這題難在分析題意以及拓撲排序的運用。

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