1. 程式人生 > 其它 >「Codeforces 1131D」Gourmet Choice

「Codeforces 1131D」Gourmet Choice

Description

美食家 Apple 先生是一家美食雜誌的主編。他會用一個正整數來評價每一道菜。

美食家在第一天品嚐第 $n$ 道菜,第二天品嚐了 $m$ 道菜。他製作了一張 $n\times m$ 的表格,記錄了他對菜餚的評價。如果第一套中的第 $i$ 道菜比第二套中的第 $j$ 道菜好,那麼 $a_{i,j}$ 等於 `>`;如果要差,那麼 $a_{i,j}$ 等於 `<`。菜餚可能同樣美味,那麼 $a_{i,j}$ 等於 `=`。

現在 Apple 先生想讓你幫他評價每道菜。由於他是非常嚴格的,他會對菜餚進行評估,以便使用的最大整數儘可能小。但是 Apple 先生也很公平,如果 $a_{i,j}$ 為 `<`,那麼給第一套中第 $i$ 道菜的評價一定小於第二套中第 $j$ 道菜。如果 $a_{i,j}$ 是 `>` 那麼應該要更大。如果 $a_{i,j}$ 為 `=`,那麼這兩個數字要相等。

幫助 Apple 先生評價這兩套中的每一道菜,使之符合他的感受,並滿足最大數字儘可能小。如果有解則輸出 `Yes` 和評價的數字;否則輸出 `No`。

資料範圍:$1\le n,m\le 10^3$。


首先我們把 = 給處理掉,把所有相等的點縮在一起。如果同一個並查集中的點有 <> 關係顯然無解。

此時我們得到了一個有向圖,直接對它拓撲排序,如果有環則無解,否則輸出方案。

const int N = 2e3 + 10;
vector<int>e[N];
string s[N];
int f[N], p[N], d[N];
int find(int x) {return x == f[x] ? x : f[x] = find(f[x]);}
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; ++i) cin >> s[i];
    for (int i = 0; i < n + m + 1; ++i) f[i] = i;
    for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j)
            if (s[i][j] == '=') {
                int u = find(i), v = find(n + j);
                f[u] = v;
            }
    for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j)
            if (s[i][j] != '=') {
                int u = find(i), v = find(n + j);
                if (s[i][j] == '<') {
                    e[u].push_back(v);
                    d[v] += 1;
                } else {
                    e[v].push_back(u);
                    d[u] += 1;
                }
            }
    queue<int>q;
    for (int i = 0; i < n + m; ++i) if (find(i) == i and !d[i])q.push(i), p[i] = 1;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int v : e[u])
            if (!(--d[v])) {
                q.push(v);
                p[v] = p[u] + 1;
            }
    }
    for (int i = 0; i < n + m; ++i) if (!(p[i] = p[find(i)])) {cout << "No\n"; return 0;}
    cout << "Yes\n";
    for (int i = 0; i < n; ++i) cout << p[i] << " \n"[i == n - 1];
    for (int i = 0; i < m; ++i) cout << p[i + n] << " ";
}

The desire of his soul is the prophecy of his fate
你靈魂的慾望,是你命運的先知。