1. 程式人生 > 其它 >Codeforces Global Round 15 D. Array Differentiation

Codeforces Global Round 15 D. Array Differentiation

Codeforces Global Round 15 D. Array Differentiation

題意:給定一個序列 \(a_1,a_2,...,a_n\)​ ,問是否存在一個序列 \(b_1, b_2, ..., b_n\)​ ,使得對任意 \(a_i\)​ ,都有 \(b_j - b_k = a_i \ (1 \leq j、k \leq n)\)​ 。

分析:對於任意一個 \(a_i\)​ ,都存在一個關係,把 \(b_i\)​ 看作點權, \(a_i\)​ 看作邊權,如果 \(b_j - b_k = a_i\)​ ,則從 \(j\)​ 向 \(k\)​​​ 連一條邊。則問題變成了一張 \(G(n, n)\)

​​ 圖,那麼圖中一定存在一個環(弱連通圖上),由於關係是相減的,如果存在序列 \(b\)​ ,那麼環上所有邊權之和在同方向下一定為 \(0\)​​​ (列舉方向,也就是正負號,列舉箭頭方向保持一致),只要存在這麼一條環即可。

Code

// cur表示列舉到了哪個點,sum表示環上貢獻總和,is_loop表示目前是否形成環
bool check (int cur, int sum, int is_loop) // 可能存在空環
{
    if (cur > n)
        return sum == 0 && is_loop; // 貢獻總和為0且形成了環

    bool res = false;
    res |= check(cur+1, sum, is_loop); // 環上不包含這個點
    res |= check(cur+1, sum + a[cur], 1); // 環上包含,且該值在環上的貢獻為正數
    res |= check(cur+1, sum - a[cur], 1); // 環上包含,且該值在環上的貢獻為正數
    return res;
}

void solve ()
{
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    puts(check(1, 0, 0) ? "YES" : "NO");
}