默……停了好久……終於良心發現了……
Box Relations |
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) |
Total Submission(s): 84 Accepted Submission(s): 35 |
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):
|
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 |
這題顯然我是不會做的……(喂!好得意嘛!)看大家說要用拓撲排序……那……那就先看看拓撲是個啥吧……
對一個有向無環圖(Directed Acyclic Graph簡稱DAG)G進行拓撲排序,是將G中所有頂點排成一個線性序列,使得圖中任意一對頂點u和v,若<u,v> ∈E(G),則u在線性序列中出現在v之前。 --百度百科
so……不如……還是直接抄代碼好了………………sign
#include <iostream>
using namespace std;
#define N 2001
#define M 500000
int NE;
int n;
int head[4][N];
int q[4][N];
int degree[4][N];
int ans[4][N];
struct node
{
int v,next;
node(){};
node(int a,int b)
{
next=a;v=b;
}
}E[M];
void insert(int type,int u,int v)
{
E[NE]=node(head[type][u],v);//add a new edge
head[type][u]=NE++;
degree[type][v]++;
}
bool topsort(int type)
{
int front=1,top=0;
for(int i=1;i<=2*n;i++)
{
if(degree[type][i]==0)
{
q[type][top++]=i;
degree[type][i]--;
}
}
while(front<top)
{
int u=q[type][front++];
for(int i=head[type][u];i!=-1;i=E[i].next)
{
int v=E[i].v;
degree[type][v]--;
if(degree[type][v]==0)
{
q[type][top++]=v;
degree[type][v]--;
}
}
}
return top==2*n;
}
void solve()
{
for(int i=1;i<=3;i++)
{
if(!topsort(i))
{
cout<<"IMPOSSIBLE"<<endl;
return ;
}
}
cout<<"POSSIBLE"<<endl;
for(int i=1;i<=3;i++)
{
for(int j=0;j<2*n;j++)
{
ans[i][q[i][j]]=j;
}
}
for(int i=1;i<=n;i++)
{
cout<<ans[1][i]<<" "<<ans[2][i]<<" "<<ans[3][i]<<endl;
cout<<ans[1][i+n]<<" "<<ans[2][i+n]<<" "<<ans[3][i+n]<<endl;
}
}
void init()
{
NE=0;
memset(degree,0,sizeof(degree));
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
for(int j=1;j<=3;j++)
insert(j,i,i+n);
}
int main()
{
char ch[2];
int a,b;
int k=1;//record the number of case for print
int m;
while(cin>>n>>m,n||m)
{
init();
while(m--)
{
cin>>ch>>a>>b;
if(ch[0]=='I')
{
for(int i=1;i<=3;i++)
{
insert(i,a,b+n);
insert(i,b,a+n);
}
}
else
insert(ch[0]-'X'+1,a+n,b);
}
cout<<"Case "<<k++<<": ";
solve();
cout<<endl;
}
}
居然超時了……情何以堪……重點是連超時的代碼我都看不懂………………
時間靜靜的過去了一個多月……終於繞了一圈回到了這道題(這也是我喜歡step的地方……必須面對自己慘淡的人生啊……)差點又碼一遍錯的代碼……這次……讓我好好理解一下吧至少……話說這次錯的代碼交上去是system error。。。那是個毛?!
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define N 2002
#define M 500000
struct node{
int ed;
node *next;
}e[M],*head[4][N];
int pos;
int n;
int q[4][N];
int in[4][N];//number of n's in-degree
int ans[4][N];
void insert(int type,int a,int b);
void init()
{
pos=0;
memset(head,0,sizeof(head));
memset(in,0,sizeof(in));
for(int i=1;i<=n;i++)
for(int j=1;j<=3;j++)
insert(j,i,i+n);//every cube has its original requirement
}
void insert(int type,int a,int b)
{
e[pos].ed=b;//the end point of the edge
e[pos].next=head[type][a];//if have several end point
head[type][a]=&e[pos++];//head point to now edge
in[type][b]++;//the end point's in-degree ++
}
bool topsort(int type)
{
int front,top;
front=top=0;
for(int i=1;i<=2*n;i++)
{
if(!in[type][i])//no in-degree
{
q[type][top++]=i;//enqueue
}
}
while(front<top)
{
int u=q[type][front++];
for(node *p=head[type][u];p;p=p->next)//tear all the edge of the start point
{
in[type][p->ed]--;//tear the edge, the end point's in-degree minus
if(!in[type][p->ed])//check if the end point has no in-degree
{
q[type][top++]=p->ed;//enqueue
}
}
}
return top==2*n;//all point enqueued
}
void solve()
{
for(int i=1;i<=3;i++)
{
bool flag=topsort(i);
if(!flag)
{
puts("IMPOSSIBLE");
return;
}
}
puts("POSSIBLE");
for(int i=0;i<2*n;i++)
for(int j=1;j<=3;j++)
ans[j][q[j][i]]=i;
for(int i=1;i<=n;i++)
printf("%d %d %d %d %d %d\n", ans[1][i], ans[2][i], ans[3][i],ans[1][i + n], ans[2][i + n], ans[3][i + n]);
}
int main(void){
char ch[2];
int a,b;
int cas=1;
int r;
while(cin>>n>>r,n||r){
init();
while(r--){
//cin>>ch>>a>>b; //if use cin...timelimit exceeded....no...
scanf("%s %d %d", &ch, &a, &b);
if(ch[0]=='I'){
for(int i=1;i<=3;i++){
insert(i,a,b+n);
insert(i,b,a+n);
}
}
else
insert(ch[0]-'X'+1,a+n,b);//this is great
}
printf("Case %d: ",cas++);
solve();
printf("\n");
}
return 0;
}
算是差不多知道是怎麼回事了……但讓我自己寫果然還是有些難吧……
用的是一個三維的拓撲排序,其實就是建一個3維數組分別加入邊,排序和輸出而已……
可以簡化成一維的先理解下。
就是每個線段有兩個端點,a+n大於a,即a端指向a+n端(共n條線段),即a->a+n。兩個線段(a,b)間有兩種情況。1相交,則a+n大於b,b+n大於a。2.x a b,即b大於a+n。
然後把所有的邊放在一起拓撲排序~具體如下:
這樣得到一個拓樸序列 v 1 , v 6 , v 4 , v 3 , v 2 , v 5 。
是的請叫我粘貼黨。
代碼實現也差不多,找無入度點,找它指向的所有後續點,刪邊減點。這裏的node中用的是next指針,指向下一個由同一起始點指向的終點。如對於1有三個終點234,則1指向的終點可能是4,而4會指向3,3會指向2。……總覺得好麻煩。
這個程序除了還有些使用困難的拓撲排序外,還有兩個小點。一是cin真的要慎用。140ms到超時,就是這麼可怕。二是自己腦殘了居然把i和j設成全局變量!!腦子無疑是被槍打了。害我調半天混蛋- -
終於over了。5.3進軍!頑張る!!