Codeforces Round #726 (Div. 2) F. Figure Fixing

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=aiti ,那么只需要让所有 a i a_i ai 的权值为 0 0 0 即可;
  • 每次操作所有权值的和变化 2 ⋅ k 2\cdot k 2k ,不改变权值和的奇偶性,所以如果当前权值和的奇偶性与目标权值和的奇偶性不同,则一定不可能;
  • 如果这个图是二分图,将图染成两种颜色。那么每次操作一定会对图的两个部分同时生效,所以要求二分图的两个部分 ∑ 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43860866/article/details/118227102