题目分析

本题要求我们通过最少的操作次数,将一个初始全为 000n×nn \times nn×n 矩阵转换为目标符号矩阵。

操作定义

每次操作可以选择:

  • 将某一整行的所有元素同时 +1+1+1−1-11
  • 将某一整列的所有元素同时 +1+1+1−1-11

符号约束

目标矩阵中每个位置的符号有三种可能:

  • + 表示该位置最终值 >0> 0>0
  • - 表示该位置最终值 <0< 0<0
  • 0 表示该位置最终值 =0= 0=0

关键观察

设第 iii 行进行的净操作次数为 RiR_iRi(加为正,减为负),第 jjj 列进行的净操作次数为 CjC_jCj,则矩阵中 (i,j)(i, j)(i,j) 位置的最终值为:

Ai,j=Ri+Cj A_{i,j} = R_i + C_j Ai,j=Ri+Cj

因此,问题转化为:

  • 寻找整数序列 R1,R2,…,RnR_1, R_2, \dots, R_nR1,R2,,RnC1,C2,…,CnC_1, C_2, \dots, C_nC1,C2,,Cn
  • 满足所有符号约束
  • 最小化 ∑i=1n∣Ri∣+∑j=1n∣Cj∣\sum_{i=1}^{n} |R_i| + \sum_{j=1}^{n} |C_j|i=1nRi+j=1nCj

解题思路

1. 约束条件的形式化

对于每个位置 (i,j)(i, j)(i,j),根据目标符号有:

  • 若为 +Ri+Cj≥1R_i + C_j \ge 1Ri+Cj1
  • 若为 -Ri+Cj≤−1R_i + C_j \le -1Ri+Cj1
  • 若为 0Ri+Cj=0R_i + C_j = 0Ri+Cj=0

2. 变量代换与差分约束转化

这是本题最精妙的一步。我们引入新的变量表示,令:

  • Xi=RiX_i = R_iXi=Ri,其中 0≤i<n0 \le i < n0i<n
  • Xn+j=−CjX_{n+j} = -C_jXn+j=Cj,其中 0≤j<n0 \le j < n0j<n

则原有的约束可以统一改写为:

对于 + 约束:
Ri+Cj≥1⇒Ri−(−Cj)≥1⇒Xn+j−Xi≤−1 R_i + C_j \ge 1 \Rightarrow R_i - (-C_j) \ge 1 \Rightarrow X_{n+j} - X_i \le -1 Ri+Cj1Ri(Cj)1Xn+jXi1

对于 - 约束:
Ri+Cj≤−1⇒Ri−(−Cj)≤−1⇒Xi−Xn+j≤−1 R_i + C_j \le -1 \Rightarrow R_i - (-C_j) \le -1 \Rightarrow X_i - X_{n+j} \le -1 Ri+Cj1Ri(Cj)1XiXn+j1

对于 0 约束:
Ri+Cj=0⇒Ri−(−Cj)=0⇒{Xi−Xn+j≤0Xn+j−Xi≤0 R_i + C_j = 0 \Rightarrow R_i - (-C_j) = 0 \Rightarrow \begin{cases} X_i - X_{n+j} \le 0 \\ X_{n+j} - X_i \le 0 \end{cases} Ri+Cj=0Ri(Cj)=0{XiXn+j0Xn+jXi0

所有约束都转化为了标准形式 Xv−Xu≤wX_v - X_u \le wXvXuw,这正是差分约束系统的标准形式。

3. 图论建模

将每个变量 XkX_kXk 视为图中的一个节点(共 2n2n2n 个节点),对于每条约束 Xv−Xu≤wX_v - X_u \le wXvXuw,添加一条从 uuuvvv 的边,权值为 www

具体建图规则:

  • + :添加边 n+j→in+j \to in+ji,权值为 −1-11
  • - :添加边 i→n+ji \to n+jin+j,权值为 −1-11
  • 0 :添加边 i→n+ji \to n+jin+jn+j→in+j \to in+ji,权值均为 000

4. 求解差分约束系统

使用 SPFA\texttt{SPFA}SPFA 算法求解最短路:

  • 将所有节点的初始距离设为 000,并全部加入队列
  • 运行 SPFA\texttt{SPFA}SPFA,同时记录每个节点的入队次数
  • 如果某个节点入队次数达到 2n2n2n 次,说明图中存在负环,约束系统无解,输出 −1-11
  • 否则,distdistdist 数组保存了一组可行解,即每个 XkX_kXk 的一个可行取值

为什么初始距离设为 000 且全部入队?

  • 差分约束系统需要添加超级源点,但我们可以等价地将所有点初始距离设为 000 并入队,效果相同且更简洁
  • 这样可以找到一组使得所有变量尽可能接近 000 的解

5. 还原变量并最小化操作次数

得到 XXX 数组后,还原原始变量:

  • Ri=XiR_i = X_iRi=Xi
  • Cj=−Xn+jC_j = -X_{n+j}Cj=Xn+j

由于差分约束系统只确定了变量之间的相对关系,我们可以给所有 RiR_iRi 加上一个偏移量 shiftshiftshift

  • Ri′=Ri+shiftR_i^{'} = R_i + shiftRi=Ri+shift
  • 由于 Xn+j=−CjX_{n+j} = -C_jXn+j=Cj 也包含了相同的相对关系,对应地 Cj′=Cj−shiftC_j^{'} = C_j - shiftCj=Cjshift

操作总次数为:
∑i=0n−1∣Ri+shift∣+∑j=0n−1∣Cj−shift∣ \sum_{i=0}^{n-1} |R_i + shift| + \sum_{j=0}^{n-1} |C_j - shift| i=0n1Ri+shift+j=0n1Cjshift

代入 Cj=−Xn+jC_j = -X_{n+j}Cj=Xn+j,得:
∑i=0n−1∣Xi+shift∣+∑j=0n−1∣−Xn+j−shift∣ \sum_{i=0}^{n-1} |X_i + shift| + \sum_{j=0}^{n-1} |-X_{n+j} - shift| i=0n1Xi+shift+j=0n1Xn+jshift

我们只需在 shift∈[−n,n]shift \in [-n, n]shift[n,n] 范围内枚举,计算每种情况下的总操作次数,取最小值即可。

为什么枚举范围是 [−n,n][-n, n][n,n]

  • 由于每个变量的值不会偏离 000 太远(否则操作次数会很大),在 n≤100n \le 100n100 时,[−n,n][-n, n][n,n] 的范围已经足够覆盖最优解

6. 时间复杂度分析

  • 建图:O(n2)O(n^2)O(n2)
  • SPFA\texttt{SPFA}SPFA 算法:平均时间复杂度 O(kE)O(kE)O(kE),其中 E=O(n2)E = O(n^2)E=O(n2)kkk 为常数
  • 枚举平移量:O(n2)O(n^2)O(n2)

总体时间复杂度 O(n2)O(n^2)O(n2),在 n≤100n \le 100n100 时可以在毫秒级完成所有测试用例。


参考代码

// Sign of a Matrix
// UVa ID: 11671
// Verdict: Accepted
// Submission Date: 2026-04-12
// UVa Run Time: 0.010s
//
// 版权所有(C)2026,邱秋。metaphysis # yeah dot net

#include <bits/stdc++.h>
using namespace std;

const int INF = 1e9;
const int MAXN = 205;

struct Edge {
    int to, weight;
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n, caseNum = 0;
    while (cin >> n && n != -1) {
        vector<string> grid(n);
        for (int i = 0; i < n; ++i) cin >> grid[i];
        
        int total = 2 * n;
        vector<vector<Edge>> adj(total);
        
        // 根据符号建图
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j) {
                int u = i;          // R[i]
                int v = n + j;      // -C[j]
                if (grid[i][j] == '+') 
                    adj[v].push_back({u, -1});  // -C[j] - R[i] <= -1
                else if (grid[i][j] == '-') 
                    adj[u].push_back({v, -1});  // R[i] - (-C[j]) <= -1
                else {  // '0'
                    adj[u].push_back({v, 0});   // R[i] - (-C[j]) <= 0
                    adj[v].push_back({u, 0});   // -C[j] - R[i] <= 0
                }
            }
        
        // SPFA 求最短路并检测负环
        vector<int> dist(total, 0);  // 所有点初始距离为 0
        vector<int> cnt(total, 0);
        vector<bool> inQueue(total, true);
        queue<int> q;
        
        for (int i = 0; i < total; ++i) q.push(i);
        
        bool hasNegCycle = false;
        while (!q.empty() && !hasNegCycle) {
            int u = q.front();
            q.pop();
            inQueue[u] = false;
            
            for (const Edge& e : adj[u]) {
                int v = e.to;
                int w = e.weight;
                if (dist[v] > dist[u] + w) {
                    dist[v] = dist[u] + w;
                    cnt[v] = cnt[u] + 1;
                    if (cnt[v] >= total) {
                        hasNegCycle = true;
                        break;
                    }
                    if (!inQueue[v]) {
                        q.push(v);
                        inQueue[v] = true;
                    }
                }
            }
        }
        
        cout << "Case " << ++caseNum << ": ";
        if (hasNegCycle) {
            cout << -1 << "\n";
            continue;
        }
        
        // 计算最小操作次数:枚举平移量
        int ans = INF;
        for (int shift = -n; shift <= n; ++shift) {
            int sum = 0;
            for (int i = 0; i < n; ++i) 
                sum += abs(dist[i] + shift);           // R[i]
            for (int j = 0; j < n; ++j) 
                sum += abs(-dist[n + j] - shift);      // C[j] = -(-C[j]) 的相反数
            ans = min(ans, sum);
        }
        
        cout << ans << "\n";
    }
    return 0;
}

总结

本题是一道经典的差分约束系统应用题,核心难点在于:

  1. 问题转化:将矩阵操作转化为行变量和列变量的线性组合
  2. 变量代换:通过令 Xn+j=−CjX_{n+j} = -C_jXn+j=Cj,将所有约束统一为 Xv−Xu≤wX_v - X_u \le wXvXuw 的形式
  3. 图论建模:将差分约束转化为有向图中的边,使用 SPFA\texttt{SPFA}SPFA 算法求解
  4. 最优化处理:通过枚举平移量找到使操作次数最小的解

掌握这种将代数约束转化为图论模型的方法,对于解决许多组合优化问题都有很大帮助。差分约束系统不仅适用于本题,在求解诸如区间约束、任务调度等问题时也有广泛应用。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐