1 条题解
-
0
这个 trick 做过 次了,还得调半天。
限制形如两个变量的和或差,我们把限制连边,找出连通块,之后随便钦定一个点的点权是 ,看看能否把 解出来,是否出现矛盾,如果都没有,就有一个自由的东西可以自己确定。
这个题就是完全裸的这种题。
我们把边建出来,并打好标记。枚举每个连通块,钦定一个点的点权为 ,进行 DFS,则每个这个连通块中的点都是 样子的点权(),如果同一个点同时需要时两个不同的 的 和 ,直接报告无解。如果同一个点需要是 还得是 ,我们可以解出 (这题还得判断 必须是整数),用这个确定的 对这个连通块进行覆盖并判断是否无解。
对于没有确定 的连通块的每个点。如果它的 ,我们标记一个 时答案可以加一。 反之。用
std::map维护差分。这样这题就做完了,上代码。
:::success[代码]
#include <bits/stdc++.h> #define int long long using namespace std; #define MAXN 200005 int T, n, m, l[MAXN], r[MAXN], k[MAXN], b[MAXN]; bool vis[MAXN]; map<int, int> segs[MAXN]; vector<pair<int, int> > e[MAXN]; pair<int, int> dfs(int id, int K, int B) { // first : 0 不可能 / 1 正常 / 2 已确定 // cout << "dfs " << id << ' ' << K << ' ' << B << endl; if (vis[id]) { if (K == k[id]) { if (B == b[id]) { return {1, 0}; } else { return {0, 0}; } } else { if ((b[id] + B) & 1) { return {0, 0}; } // b[id] + (k[id] > 0 ? 1 : -1) * x = B + (K > 0 ? 1 : -1) * x int x = (B - b[id]) / (k[id] > 0 ? 2 : -2); // cout << "x = " << x << endl; return {2, x}; } } vis[id] = 1; k[id] = K; b[id] = B; for (pair<int, int> i : e[id]) { pair<int, int> t = dfs(i.first, -K, i.second - B); if (t.first == 0) { return t; } else if (t.first == 2) { return t; } } return {1, 0}; } void dfs_erase_vis(int id) { vis[id] = 0; for (pair<int, int> i : e[id]) { if (vis[i.first]) { dfs_erase_vis(i.first); } } } bool dfs_fill(int id, int x) { k[id] = 0; b[id] = x; vis[id] = 1; for (pair<int, int> i : e[id]) { if (vis[i.first]) { if (b[i.first] + x == i.second) { continue; } else { return 0; } } if (!dfs_fill(i.first, i.second - x)) { return 0; } } return 1; } signed main() { cin >> T; while (T--) { cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> l[i]; } for (int i = 1; i <= n; i++) { cin >> r[i]; } for (int i = 1, u, v, w; i <= m; i++) { cin >> u >> v >> w; e[u].push_back({v, w}); e[v].push_back({u, w}); } for (int i = 1; i <= n; i++) { // cout << "i = " << i << endl; if (!vis[i]) { pair<int, int> t = dfs(i, i, 0); if (t.first == 0) { cout << "-1\n"; goto END; } else if (t.first == 2) { dfs_erase_vis(i); if (!dfs_fill(i, t.second)) { cout << "-1\n"; goto END; } } } // cout << "try fill " << i << endl; // for (int i = 1; i <= n; i++) { // cout << vis[i] << ' '; // } // cout << endl; // for (int i = 1; i <= n; i++) { // cout << k[i] << ' '; // } // cout << endl; // for (int i = 1; i <= n; i++) { // cout << b[i] << ' '; // } // cout << endl; } if (0) { END: for (int i = 0; i < MAXN; i++) { l[i] = r[i] = k[i] = b[i] = vis[i] = 0; segs[i].clear(); e[i].clear(); } continue; } int ans = 0; for (int i = 1; i <= n; i++) { if (k[i] == 0) { ans += (l[i] <= b[i] && b[i] <= r[i]); } else { l[i] -= b[i]; r[i] -= b[i]; if (k[i] < 0) { k[i] *= -1; l[i] *= -1; r[i] *= -1; swap(l[i], r[i]); } segs[k[i]][l[i]]++; segs[k[i]][r[i] + 1]--; } } for (int i = 1; i <= n; i++) { int sum = 0, maxn = 0; for (pair<int, int> j : segs[i]) { sum += j.second; maxn = max(maxn, sum); } ans += maxn; } // cout << "ans = "; cout << ans << '\n'; for (int i = 0; i < MAXN; i++) { l[i] = r[i] = k[i] = b[i] = vis[i] = 0; segs[i].clear(); e[i].clear(); } } return 0; }:::
- 1
信息
- ID
- 5397
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 37
- 已通过
- 8
- 上传者