默……停了好久……终于良心发现了……
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进军!頑張る!!