给你两个边集一样的图,点有黑白两色,而且有点权。
你操作若干次,每次选择一条边,把连着的两个点点权交换,若两点同色则同时反色。
然后问你 A 图能否通过操作得到 B 图。
发现部分分有个二分图,思考一下。
发现这个颜色的操作很迷,考虑放到二分图上。
发现如果你把其中的一边的点都反色一下,那操作就变成了交换两边的颜色。
那就跟交换边权统一了。
那我们就可以对于每个连通块,查询它们有的点权+颜色集合是否一样即可。
接着问题是不是二分图,考虑会有什么影响。
而且首先一定会有的是奇环。
然后考虑操作这条边会怎样。
那你可以内部选一样的颜色消去,那也就是说,你两个图,需要的颜色的差是偶数倍的话,你就可以把它转成不相差。
然后也就没啥了,那如果可以的话你就不用判断颜色了。
#include
#include
#include
using namespace std;
const int N = 1e6 + 100;
struct node {
int to, nxt;
}e[N << 1];
int T, n, m, le[N], KK, col[N], tot;
int a[N], b[N], G1, G2;
vector <int> A[2], B[2];
char s[N], t[N];
bool Op[N], ji;
void clr() {
for (int i = 1; i <= n; i++) le[i] = 0; KK = 0;
for (int i = 1; i <= n; i++) col[i] = 0; tot = 0;
}
void add(int x, int y) {
e[++KK] = (node){y, le[x]}; le[x] = KK;
}
void dfs(int now, int op) {
if (col[now]) {
if (Op[now] != op) ji = 1;
return ;
}
col[now] = tot; Op[now] = op;
A[(s[now] == 'R') ^ op].push_back(a[now]);
B[(t[now] == 'R') ^ op].push_back(b[now]);
if (s[now] == 'R') G1++; if (t[now] == 'R') G2++;
for (int i = le[now]; i; i = e[i].nxt)
dfs(e[i].to, op ^ 1);
}
bool same(vector <int> a, vector <int> b) {
sort(a.begin(), a.end()); sort(b.begin(), b.end());
return a == b;
}
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++) {
int x, y; scanf("%d %d", &x, &y);
add(x, y); add(y, x);
}
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
scanf("%s", s + 1);
for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
scanf("%s", t + 1);
bool yes = 1;
for (int i = 1; i <= n; i++)
if (!col[i]) {
A[0].clear(); A[1].clear(); B[0].clear(); B[1].clear();
G1 = G2 = 0; ji = 0;
tot++; dfs(i, 0);
if (ji) {
for (int j = 0; j < A[1].size(); j++) A[0].push_back(A[1][j]);
for (int j = 0; j < B[1].size(); j++) B[0].push_back(B[1][j]);
if ((G1 - G2) % 2 != 0 || !same(A[0], B[0])) {
yes = 0; break;
}
}
else {
if ((G1 - G2) % 2 != 0 || !same(A[0], B[0]) || !same(A[1], B[1])) {
yes = 0; break;
}
}
}
clr();
if (yes) printf("YES\n");
else printf("NO\n");
}
return 0;
}