D - Good Tuple Problem atcoder abc 327
D - Good Tuple Problem
https://atcoder.jp/contests/abc327/tasks/abc327_d
思路 - dfs染色判断
https://www.zhihu.com/question/292465499
判断二分图
的常见方法是染色法:用两种颜色,对所有顶点逐个染色,且相邻顶点染不同的颜色
如果发现相邻顶点染了同一种颜色,就认为此图不为二分图
当所有顶点都被染色,且没有发现同色的相邻顶点,就退出
Code - dfs染色判断
https://atcoder.jp/contests/abc327/submissions/47406923
#include<cstdio> #include<iostream> #include<vector> using namespace std; int n,m,color[200010], a[200010], b[200010]; vector<int> edge[200010]; int dfs(int x,int c){ color[x]=c ; for(int i=0;i<edge[x].size();i++){ int v=edge[x][i]; if(color[v]==color[x]){ return 0; } if(color[v]==0 && !dfs(v,-c)){ return 0; } } return 1; } void solve(){ for(int i=1;i<=n;i++){ if(color[i]==0){ if(!dfs(i,1)){ printf("No"); return ; } } } printf("Yes"); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ cin >> a[i]; } for(int i=1;i<=m;i++){ cin >> b[i]; } for(int i=1;i<=m;i++){ int x,y; x = a[i]; y = b[i]; // scanf("%d%d",&x,&y); edge[x].push_back(y); edge[y].push_back(x); } solve(); return 0; }
思路 -- 并查集
https://www.cnblogs.com/Jojo-L/p/16520445.html
如果图是二分图的话,那么图中每个顶点的所有邻接点都应该属于同一集合,且不与顶点处于同一集合。因此可以使用并查集来解决这个问题:
遍历图中每个顶点,将当前顶点的所有邻接点进行合并,并判断这些邻接点中是否存在某一邻接点已经和当前顶点处于同一个集合中,若是,则说明不是二分图。
https://zhuanlan.zhihu.com/p/161082172
遍历图中每个顶点:
将当前顶点的所有邻接点进行合并判断是否存在邻接点与当前顶点已经在一个集合中了,若存在,则说明不是二分图
Code
/** * author: tourist * created: 10.07.2022 18:40:44 **/ #include <bits/stdc++.h> using namespace std; #ifdef LOCAL #include "algo/debug.h" #else #define debug(...) 42 #endif class dsu { public: vector<int> p; int n; dsu(int _n) : n(_n) { p.resize(n); iota(p.begin(), p.end(), 0); } inline int get(int x) { return (x == p[x] ? x : (p[x] = get(p[x]))); } inline bool unite(int x, int y) { x = get(x); y = get(y); if (x != y) { p[x] = y; return true; } return false; } inline bool is_connected(int x, int y){ x = get(x); y = get(y); if (x == y) { return true; } return false; } }; int main() { ios::sync_with_stdio(false); cin.tie(0); int tt = 1; while (tt--) { int n, m; cin >> n >> m; dsu d(n); vector<int> a(m); vector<int> b(m); for (int i = 0; i < m; i++) { cin >> a[i]; } for (int i = 0; i < m; i++) { cin >> b[i]; } vector<vector<int>> mp(n); for (int i = 0; i < m; i++) { int x = a[i]; int y = b[i]; x--; y--; mp[x].push_back(y); mp[y].push_back(x); } for (int i = 0; i < n; i++) { if (mp[i].size() == 0){ continue; } int first_neighbor = *mp[i].begin(); for(auto next : mp[i]){ if (d.is_connected(i, next)){ cout << "No" << endl; return 0; } d.unite(first_neighbor, next); } } cout << "Yes" << '\n'; } return 0; }
思路 -- 扩展域并查集
https://www.cnblogs.com/zsh-notes/p/12820467.html
把每个节点扩展为两个节点(一正一反),若a与b不能在一起(在同一个集合),则把a的正节点与b的反节点放一起,把b的正节点与a的反节点放一起,这样就解决了a与b的冲突。若发现a的正节点与b的正节点已经在一起,那么说明之前的某对关系与(a,b)这对关系冲突,不可能同时满足,即不能成功完成整个操作。
https://www.cnblogs.com/yHan234/p/16473336.html
https://www.zhihu.com/question/474576285
证明:假设二分图中的环是奇数环。
设一个环,x1,x2,x3,,,,x(2*k-1),k>=1且为整数。相邻两点有边连接,x1与x(2*k-1)相连。
由二分图定义可知:x1与x2分别在X集合和Y集合,由于x2与x3的关系可知x3在X集合,则x4在Y集合,以此类推,可得奇数点在X集合,偶数点在Y集合,那么点x(2*k-1)则在X集合中,即与x1同为一个集合,但有之间假设的x1与x(2*k-1)有连边,那么此时就与二分图定义不符,这二分图中的环不可能是奇数环。
Code -- 扩展域并查集
https://atcoder.jp/contests/abc327/submissions/47434599
/** * author: tourist * created: 10.07.2022 18:40:44 **/ #include <bits/stdc++.h> using namespace std; #ifdef LOCAL #include "algo/debug.h" #else #define debug(...) 42 #endif class dsu { public: vector<int> p; int n; dsu(int _n) : n(_n) { p.resize(n); iota(p.begin(), p.end(), 0); } inline int get(int x) { return (x == p[x] ? x : (p[x] = get(p[x]))); } inline bool unite(int x, int y) { x = get(x); y = get(y); if (x != y) { p[x] = y; return true; } return false; } }; int main() { ios::sync_with_stdio(false); cin.tie(0); int tt = 1; // cin >> tt; while (tt--) { int n, m; cin >> n >> m; vector<int> deg(n); dsu d(2 * n); vector<int> a(m); vector<int> b(m); for (int i = 0; i < m; i++) { cin >> a[i]; } for (int i = 0; i < m; i++) { cin >> b[i]; } for (int i = 0; i < m; i++) { int x = a[i]; int y = b[i]; x--; y--; deg[x] += 1; deg[y] += 1; d.unite(x, y + n); d.unite(x + n, y); } bool ok = true; for (int i = 0; i < n; i++) { // if (deg[i] > 2) { // ok = false; // } if (d.get(i) == d.get(i + n)) { ok = false; } } cout << (ok ? "Yes" : "No") << '\n'; } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
2022-11-10 How JWT (JSON Web Token) authentication works?
2022-11-10 FASTAPI OAuth2 Scopes
2022-11-10 OAuth2
2017-11-10 Lua Doc生成工具