题意:
给出n个点,m条边的无向图。对于图中的每个点存在当前点权vi和目标点权ti。每次操作可以将同一条边相连的两个点的当前点权同时增加或减少任意值,可以操作任意次。问是否能将所有点的当前点权变成目标点权。
题解:
设改变点权为目标点权减去当前点权。偶数距离的点可以共享改变点权,奇数距离的点可以同时变更改变点权。若存在某个环,使得两个点之间既存在奇数距离,又存在偶数距离。那么两组点之间就共通了,这时判断改变点权和是否是偶数即可。否则判断两组点改变点权和是否相等以供消掉。
#include <bits/stdc++.h> using namespace std; const int N = 2e5+10; typedef long long ll; int casee; int n, m, tot; int x, y; ll v1, v2; int v[N], t[N]; bool flag; int visit[N]; int head[N], nxt[N<<1], to[N<<1]; void dfs(int now, int state) { visit[now] = state + 2; if(state & 1) v1 += t[now] - v[now]; else v2 += t[now] - v[now]; for(int i = head[now]; ~i; i = nxt[i]) { int index = to[i]; if(visit[index]) { if(visit[index] == visit[now]) flag = true; continue; } dfs(index, state^1); } } int main() { scanf("%d", &casee); while(casee--) { flag = false; tot = 0; v1 = v2 = 0; scanf("%d%d", &n, &m); memset(head, -1, sizeof(int) * (n+2)); memset(visit, 0, sizeof(int) * (n+2)); for(int i = 1; i <= n; i++) scanf("%d", &v[i]); for(int i = 1; i <= n; i++) scanf("%d", &t[i]); while(m--) { scanf("%d%d", &x, &y); to[++tot] = y; nxt[tot] = head[x]; head[x] = tot; to[++tot] = x; nxt[tot] = head[y]; head[y] = tot; } dfs(1, 0); if((flag && (v1+v2+1 & 1)) || (!flag && v1 == v2)) puts("YES"); else puts("NO"); } }
package main import ( "fmt" "bufio" "io" "os" ) const N int = 2e5+10 var casee int var n, m, tot int var x, y int var v1, v2 int64 var flag bool var visit [N]int var v, t [N]int var head [N]int var nxt, to [N<<1]int func dfs (now, state int) { visit[now] = state + 2 if (state & 1) > 0 { v1 += int64(t[now] - v[now]) } else { v2 += int64(t[now] - v[now]) } for i := head[now]; i > 0; i = nxt[i] { var index int = to[i] if visit[index] > 0 { if visit[index] == visit[now] { flag = true } continue } dfs(index, state^1) } } func main() { var input io.Reader = bufio.NewReader(os.Stdin) for fmt.Fscan(input, &casee); casee > 0; casee-- { v1 = 0 v2 = 0 tot = 0 flag = false head = [N]int{} visit = [N]int{} fmt.Fscan(input, &n) fmt.Fscan(input, &m) for i := 1; i <= n; i++ { fmt.Fscan(input, &v[i]) } for i:= 1; i <= n; i++ { fmt.Fscan(input, &t[i]) } for ; m > 0; m-- { fmt.Fscan(input, &x) fmt.Fscan(input, &y) tot++; to[tot] = y; nxt[tot] = head[x]; head[x] = tot tot++; to[tot] = x; nxt[tot] = head[y]; head[y] = tot } dfs(1, 0) if ((flag && (v1+v2+1) % 2 != 0) || (!flag && v1 == v2)) { fmt.Println("YES") } else { fmt.Println("NO") } } }