Box Relations
构造题
有n个长方体,满足以下要求:
I i, j : i, j不相交
X i, j : i的x维度上的坐标都小于j的x维度上的坐标
Y,Z 同理
对每一维分别进行拓扑排序。
注意:
1、对每一维,对于长方体i,都天然满足xi1 < xi2, yi1 < yi2,zi1 < zi2。
2、对与I i, j:i, j 不相交,即两个长方体中,某一个长方体的右面一定大于另一个长方体的左面,这样有两条语句:xi1 < xj2, xi2 > xj1,两条语句缺一不可。
我的代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e3 + 5;
const int maxm = 1e5 + 5;
int n, m;
char ch;
int a, b;
int in[3][maxn], path[3][maxn], ans[3][maxn];
vector<int> e[3][maxm];
void init(){
for(int j = 0; j < 3; j++){
for(int i = 1; i <= 2*n; i++){
in[j][i] = 0; e[j][i].clear();
}
}
}
int topsort(){
for(int t = 0; t < 3; t++){
// priority_queue< int,vector<int>,greater<int> > s;
queue<int>s;
for(int i = 1; i <= 2 * n; i++){
if(in[t][i] == 0)
s.push(i);
}
int cnt = 0;
while(!s.empty()){
int x = s.front();
s.pop();
path[t][x] = cnt++;
// path[t][++cnt] = x;
for(int i = 0; i < e[t][x].size(); i++){
int y = e[t][x][i];
in[t][y]--;
if(in[t][y] == 0){
s.push(y);
}
}
}
if(cnt < 2*n) return 0;
// for(int i = 1; i <= 2 * n; i++){
// int index = path[t][i];
// ans[t][index] = i-1;
// }
// }
return 1;
}
int main(){
int num = 0;
while(cin >> n >> m){
if(n == 0 && m == 0) break;
num++;
init();
//xi1<xi2, yi1<yi2, zi1<zi2
for(int j = 0; j < 3; j++){
for(int i = 1; i <= n; i++){
e[j][i].push_back(i+n);
in[j][i+n]++;
}
}
//
for(int i = 1; i <= m; i++){
cin >> ch >> a >> b;
switch(ch){
case 'I': for(int j = 0; j < 3; j++){
e[j][a].push_back(b+n); in[j][b+n]++;
e[j][b].push_back(a+n); in[j][a+n]++;
}
break;
case 'X': e[0][a+n].push_back(b); in[0][b]++; break;
case 'Y': e[1][a+n].push_back(b); in[1][b]++; break;
case 'Z': e[2][a+n].push_back(b); in[2][b]++; break;
}
}
if(topsort() == 1){
cout << "Case " << num << ": POSSIBLE" << endl;
for(int i = 1; i <= n; i++){
// cout << ans[0][i] << " " << ans[1][i] << " " << ans[2][i] << " ";
// cout << ans[0][i+n] << " " << ans[1][i+n] << " " << ans[2][i+n]<<endl;
cout << path[0][i] << " " << path[1][i] << " " << path[2][i] << " ";
cout << path[0][i+n] << " " << path[1][i+n] << " " << path[2][i+n]<<endl;
}
}
else{
cout << "Case " << num << ": IMPOSSIBLE" << endl;
}
cout << endl;
}
}
对于答案的保存,刚开始用的是代码中斜杠//的部分,即从拓扑排序path [ ] 中再转化为ans[ ]:
- path[t] [cnt++] = x;
- ans[t] [ path[t] [i] ] = i-1;
- cout << ans[t] [i] ;
但后面参考别人代码时发现了更优的做法,遂更改为:
- path[t] [x] = cnt++;
- cout << path[t] [i] ;
wa点
刚开始疯狂wa。。。原因是把第i个长方体某一维的坐标保存为2i-1, 2i了。后面改成i, i+n就过了…
更新:并不是!是因为写错字母了!IMPOSSIBLE→INPOSSIBLE,用2i-1, 2i也是可以的!