本题加深了对差分约束的理解,并不是绝对的模板题目,但是其核心还是最短路/最长路
砝码间的关系
-
\(i<j\): 由此可以得到\(1\le i+1\le j\le 3\),即\(1\le j-i\le 2\)
-
\(i=j\): \(j-i=0\)
-
\(i>j\): \(-1\le j-i\le -2\)
-
\(i\)和\(j\)关系未知: \(-2\le j-i\le 2\)
得到砝码之间的所有关系后,我们可以建图,跑最短路和最长路,从而确定砝码的上下界
天平两边的关系
\(A+B<C_i+D_J(i\ne j)\)
通过变换,可以得到两个不等式关系:
\(A-C_i<D_j-B\)和\(A-D_j<C_i-B\)
若想这两个式子恒成立,那么必定满足\(\max(A-C_i)<\min(D_j-B)\)或\(\max(A-D_j)<min(C_i-B)\),统计符合条件的情况即可
\(A+B=C_i+D_J(i\ne j)\)
类似上面的形式,统计满足\(\max(A-C_i)=\min(A-C_i)=\max(D_j-B)=\min(D_j-B)\)或\(\max(A-D_j)=\min(A-D_j)=\max(C_i-B)=\min(C_i-B)\)的情况
\(A+B>C_i+D_J(i\ne j)\)
同理,统计满足\(\min(A-C_i)>\max(D_j-B)\)或\(\min(A-D_j)>\max(C_i-B)\)的情况
代码
#include <bits/stdc++.h>
using namespace std;
inline void Max(int &a, int b) { a = a > b ? a : b; }
inline void Min(int &a, int b) { a = a < b ? a : b; }
constexpr int N = 55;
int maxd[N][N], mind[N][N];
int n, a, b;
char s[N];
int main() {
scanf("%d%d%d", &n, &a, &b);
for (int i = 1; i <= n; i++) {
scanf("%s", s + 1);
for (int j = 1; j <= n; j++)
if (s[j] == '+') {
maxd[i][j] = 2;
mind[i][j] = 1;
} else if (s[j] == '-') {
maxd[i][j] = -1;
mind[i][j] = -2;
} else if (s[j] == '=' or i == j){
maxd[i][j] = 0;
mind[i][j] = 0;
} else {
maxd[i][j] = 2;
mind[i][j] = -2;
}
}
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
Min(maxd[i][j], maxd[i][k] + maxd[k][j]);
Max(mind[i][j], mind[i][k] + mind[k][j]);
}
}
int c[3] = {0};
for (int i = 1; i <= n; i++) {
if (i == a or i == b) continue;
for (int j = 1; j < i; j++) {
if (j == a or j == b) continue;
c[0] += maxd[j][b] < mind[a][i] or maxd[i][b] < mind[a][j];
c[1] +=
(maxd[a][i] == mind[a][i] and
maxd[j][b] == mind[j][b] and
maxd[a][i] == mind[j][b]) or
(maxd[a][j] == mind[a][j] and
maxd[i][b] == mind[i][b] and
maxd[a][j] == mind[i][b]);
c[2] += maxd[a][i] < mind[j][b] or maxd[a][j] < mind[i][b];
}
}
for (int i : c) printf("%d ", i);
return 0;
}