构造大失败
直接说正解
考虑 S,T 路径里有 i 个 x ,j 个 y 其余边最小值为 fi,j
则 dx,y≥ix+jy+fi,j⇒dx,y=min(ix+jy+fi,j)j
移项得到 fi,j≤dx,y−ix−jy⇒fi,j=max(dx,y−ix−y)
构造从 S 开始的一条链全是 x ,到 T 的链全是 y
然后在第 i 个 x 与 j 个 y 间连边,暴力求出 fi,j
最后检查一遍如果不符合就是无解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #include <iostream> using namespace std; int A, B; int d[11][11]; int f[101][101]; int main() { cin >> A >> B; for (int i = 1; i <= A; i++) { for (int j = 1; j <= B; j++) { cin >> d[i][j]; } } for (int i = 0; i <= 100; i++) { for (int j = 0; j <= 100; j++) { for (int x = 1; x <= A; x++) { for (int y = 1; y <= B; y++) { f[i][j] = max(f[i][j], d[x][y] - i * x - j * y); } } } } for (int x = 1; x <= A; x++) { for (int y = 1; y <= B; y++) { int now = 0x7f7f7f7f; for (int i = 0; i <= 100; i++) { for (int j = 0; j <= 100; j++) { now = min(now, f[i][j] + i * x + j * y); } } if (now != d[x][y]) { cout << "Impossible"; return 0; } } } cout << "Possible" << endl; cout << "202 10401" << endl; for (int i = 1; i <= 100;i++){ cout << i << " " << i + 1 << " X" << endl; } for (int i = 102; i <= 201;i++){ cout << i << " " << i + 1 << " Y" << endl; } for (int i = 0; i <= 100;i++){ for (int j = 0; j <= 100;j++){ cout << i + 1 << " " << 202 - j << " " << f[i][j] << endl; } } cout << "1 202"; return 0; }
|