【PNR#2 Div1 C】图同构(图论)

图同构

题目链接:PNR#2 Div1 C

题目大意

给你两个边集一样的图,点有黑白两色,而且有点权。
你操作若干次,每次选择一条边,把连着的两个点点权交换,若两点同色则同时反色。
然后问你 A 图能否通过操作得到 B 图。

思路

发现部分分有个二分图,思考一下。

发现这个颜色的操作很迷,考虑放到二分图上。
发现如果你把其中的一边的点都反色一下,那操作就变成了交换两边的颜色。
那就跟交换边权统一了。

那我们就可以对于每个连通块,查询它们有的点权+颜色集合是否一样即可。

接着问题是不是二分图,考虑会有什么影响。
而且首先一定会有的是奇环。
然后考虑操作这条边会怎样。
那你可以内部选一样的颜色消去,那也就是说,你两个图,需要的颜色的差是偶数倍的话,你就可以把它转成不相差。
然后也就没啥了,那如果可以的话你就不用判断颜色了。

代码

#include<cstdio> #include<vector> #include<algorithm> 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; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/PNR_2_Div1_C.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2021-10-27 【luogu P3506】MOT-Monotonicity 2(线段树)
2021-10-27 【luogu AT5160】Numbers on a Circle(贪心)(堆)
2021-10-27 【luogu AT5159】RGB Balls(贪心)
2021-10-27 【luogu P5435】基于值域预处理的快速 GCD(数学)
2021-10-27 【luogu P4338】【LOJ 2434】历史(LCT)
2021-10-27 【ybtoj高效进阶 21174】景区旅行(二分)(倍增)(状压DP)(DP)
2021-10-27 【luogu AT1999】Candy Piles(博弈论)
点击右上角即可分享
微信分享提示