F. Figure Fixing
题意
一个 n n n 个点 m m m 条边的无向图,每个点有一个当前权值 a i a_i ai 和一个目标权值 t i t_i ti。如果 u u u 和 v v v 之间有边,那么可以把 u , v u,v u,v 的权值都加 k k k ,问能否通过有限次这样的操作,使得所有点的权值变成目标权值。
题解
- 令 a i = a i − t i a_i = a_i - t_i ai=ai−ti ,那么只需要让所有 a i a_i ai 的权值为 0 0 0 即可;
- 每次操作所有权值的和变化 2 ⋅ k 2\cdot k 2⋅k ,不改变权值和的奇偶性,所以如果当前权值和的奇偶性与目标权值和的奇偶性不同,则一定不可能;
- 如果这个图是二分图,将图染成两种颜色。那么每次操作一定会对图的两个部分同时生效,所以要求二分图的两个部分 ∑ a i \sum a_i ∑ai 相等;
- 如果不是二分图,那么一定有相邻节点颜色相同,所以一定可以操作。
代码
#include <bits/stdc++.h>
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define per(i, a, n) for (int i = n; i >= a; --i)
#ifdef LOCAL
#include "Print.h"
#define de(...) W('[', #__VA_ARGS__,"] =", __VA_ARGS__)
#else
#define de(...)
#endif
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
vector<int> g[maxn];
ll a[maxn];
int col[maxn];
bool dfs(int u, int c) {
col[u] = c;
for (auto v : g[u]) {
if (col[v] && col[v] == col[u]) return 0;
else if (col[v]) continue;
if (!dfs(v, 3 - col[u])) return 0;
}
return 1;
}
int solve() {
int n, m;
scanf("%d%d", &n, &m);
rep(i, 1, n) scanf("%lld", &a[i]), g[i].clear(), col[i] = 0;
ll sum = 0;
for (int i = 1, b; i <= n; ++i) scanf("%d", &b), a[i] -= b, sum += a[i];
rep(i, 1, m) {
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
if (sum % 2) return 0 * puts("NO");
if (dfs(1, 1)) {
vector<ll> sum(3);
rep(i, 1, n) sum[col[i]] += a[i];
puts(sum[1] == sum[2] ? "YES" : "NO");
} else puts("YES");
return 0;
}
int main() {
#ifdef LOCAL
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
int T = 1;
scanf("%d", &T);
while (T--) solve();
return 0;
}