hdu 3231 Box Relations 拓撲排序 詳細解題報告

題意:

給出n(1 - 1000)個box的m(0 - 100000)個關係,邊均平行與座標軸, 讓你構造這樣的n個box, 使這些box滿足這些關係,關係有以下四種:

1. I i j :表示box i 和 box j 相交

2. X i j : 表示box i 的任意點的x座標小於box j的任意點的x座標

3. Y i j : 表示box i 的任意點的y座標小於box j的任意點的y座標.

4. Z i j : 表示box i 的任意點的z座標小於box j的任意點的z座標

如果能構造出這樣的n個box, 輸出這n個box的左下角座標和右上角座標。否則輸出impossible。

分析生氣

假設用(l, r)表示box的任一維的範圍,那麼, 對於'X'操作而言, 若要滿足box i 的x座標小於box j的x座標, 那麼,只需要r(i) < l(j), 即box i的x維最大值小於box j的x維最小值。因此,我們只需要知道這n個box的關係後從左往右構造即可, 如何構造呢 ? 假設有3個box, 'X'關係位:box2 < box1, box1 < box3, 那麼,根據這個關係我們從小到大排好序後爲:l2, r2, l1, r1, l3, r3, 那麼我們從1開始依次賦值得到1,2,3,4,5,6, 則,box1:(3,4), box2:(1,2), box3:(5,6), 滿足關係, ok, 那麼如果給出的關係是:box2 < box1, box2 < box3, 又該如何排序呢?這時候就要用到拓撲排序了, 排序出的結果可能有2種(box2 < box1 < box3 或 box2 < box3 < box1)明顯根據兩種方案寫出來的答案均滿足關係, ok, 這下解釋清楚了爲什麼要用拓撲排序。 吐舌頭  接下來, 我們要說說‘I'操作, 對於'I'操作, 要使box i 和box j 相交,那麼對於任意一維(x or y or z), 均必須滿足 l(i) < r(j), l(j) < r(i); 即任意box某維的最小值小於另一個box的該維的最大值,自己在紙上畫一下便知道了。

生氣接下來的重點就是如何來拓撲排序了, 這裏, 我們把box i的某一維的左端和右端分別用i 和 i+n來表示,因爲n最大爲1000, 然後因爲i肯定是小於i+n的, 所以把i 到 i+n連一條邊, 此後,每讀入一組關係就根據他們的大小關係連邊即可,然後拓撲排序依次賦值即可。OK了害羞, 接下來就是參考代碼了:

Code:

#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 2e3 + 10;
vector<int> vec[3][maxn];// 3表示3個維度
int in[3][maxn], n, m, kase = 0;
void init()
{
    memset(in, 0, sizeof(in));
    for (int i = 0; i < 3; i++) {
        for (int j = 1; j <= n; j++) {//把i到i+n連邊
            vec[i][j].clear();
            vec[i][j+n].clear();
            vec[i][j].push_back(j+n);
            in[i][j+n] = 1;
        }
    }
}
void read_input()
{
    char op[3]; int u, v;
    for (int i = 0; i < m; i++) {
        scanf("%s%d%d", op, &u, &v);
        if (op[0] == 'I') {
            for (int j = 0; j < 3; j++) {
                vec[j][u].push_back(v+n);
                vec[j][v].push_back(u+n);
                in[j][v+n]++; in[j][u+n]++;
            }
        }
        else {
            vec[op[0]-'X'][u+n].push_back(v);
            in[op[0]-'X'][v]++;
        }
    }
}
bool topsort(int ans[], int id)
{
    queue<int> Q;
    
    for (int i = 1; i <= n; i++) {
        if (in[id][i] == 0) Q.push(i);
    }
    int cur = 0;
    while (!Q.empty())
    {
        int now = Q.front(); Q.pop();
        ans[now] = ++ cur;
        for (int i = 0; i < vec[id][now].size(); i++) {
            if (--in[id][vec[id][now][i]] == 0) {
                Q.push(vec[id][now][i]);
            }
        }
    }
    if (cur == 2*n) return true;
    return false;
}
void solve()
{
    int flag = 0, ans[3][maxn];
    for (int i = 0; i < 3; i++) {
        if (!topsort(ans[i], i)) flag = 1;
    }
    if (flag) printf("Case %d: IMPOSSIBLE\n", ++kase);
    else {
        printf("Case %d: POSSIBLE\n", ++kase);
        for (int i = 1; i <= n; i++) {
            printf("%d %d %d %d %d %d\n", ans[0][i], ans[1][i], ans[2][i], ans[0][i+n], ans[1][i+n], ans[2][i+n]);
        }
    }
    printf("\n");
}
int main()
{
 //   freopen("/Users/apple/Desktop/in.txt", "r", stdin);
    
    while (scanf("%d%d", &n, &m))
    {
        if (!(n||m)) break;
        init();
        read_input();
        solve();
    }
    
    return 0;
}


發佈了30 篇原創文章 · 獲贊 9 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章