主要有 \(3\) 种方法:DFS / BFS / DSU
- DFS
直接遍历整张图染色,判断是否产生冲突
init(){for(int i=1;i<=n;i++) col[i]=-1;
}
bool dfs(int u,int c){col[u]=c;for(auto v:e[u]){if(col[v]==-1) return dfs(v,c^1);else if(col[v]==c) return false;}return true;
}
...
bool op=dfs(1,0);
//直接任意一点任意颜色开始即可
- BFS
跟 DFS 一样,只不过遍历的方式换了而已,不过多赘述。
- DSU
并查集可以讲一下,这个是比较方便的方法。
维护一个扩展域并查集,对于节点 \(i\) , 维护与它颜色相同的集合 \(i\) 和颜色不同的集合 \(i+n\)。
我们只需要枚举每一条边 \((u,v)\) ,然后将 \(u\) 和 \(v\) 合并,关于合并,我们假定 \(u\) 和 \(v\) 颜色不同,然后将 与 \(u\) 颜色相同的 和 与 \(v\) 颜色不同的 合并,将 与 \(v\) 颜色相同的 和 与 \(u\) 颜色不同的 合并。
全部合并完后我们就要去检查每个点 \(i\) 的颜色相同与颜色不同的集合是否冲突。
struct DSU{
...
}dsu;for(int u=1;u<=n;u++)for(int v:e[u])dsu.merge(u,v+n),dsu.merge(v,u+n);for(int i=1;i<=n;i++)if(find(i)==find(i+n)){cout<<"No";return 0;}
cout<<"Yes";