by GeneralLiu
染色法
非常容易写
先记录边
遍历节点
如果没有深搜过
那深搜它就是了
并染色
染为 1 和 -1
如果染色冲突 则 return false
最后 return true
代码
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; #define N 1000 #define M 2000 int col[N],cnt,n,m,head[N],to[M],next[M]; void add(int x,int y){ next[++cnt]=head[x]; to[cnt]=y; head[x]=cnt; } void dfs(int u,int c){ col[u]=c; for(int v,i=head[u];i;i=next[i]){ v=to[i]; if(!col[v]) dfs(v,-c); // 染 -c if(col[v]==col[u]){ // 有冲突 printf("NO"); exit(0); } } } int main(){ scanf("%d%d",&n,&m); for(int x,y,i=1;i<=m;i++){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } for(int i=1;i<=n;i++) if(!col[i]) dfs(i,1); // 默认 染色 1 printf("YES"); return 0; }
程序主体是球gay最喜欢的dfs
并查集
我们可以将每个节点抽象出两个节点 v0,v1.
v0表示v染0这种颜色,v1表示v染1这种颜色。
对于这个新图,
图中的每一条边(iq,jw)(I,j为原本的点编号,q,w为0或1),
表示i选q颜色的话,j一定要选w颜色。
上面看懂看不懂的吧
直接看代码
可以的!!
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; #define N 1000 int fa[N<<1],n,m; int find(int k){return fa[k]==k?k:fa[k]=find(fa[k]);} int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n*2;i++)fa[i]=i; for(int fx,fy,x,y,i=1;i<=m;i++){ scanf("%d%d",&x,&y); fx=find(x*2-1); fy=find(y*2); fa[fx]=fy;//一个染白则另一个染黑 fx=find(x*2); fy=find(y*2-1); fa[fx]=fy;//一个染黑则另一个染白 } for(int i=1;i<=n;i++) if(find(i*2)==find(i*2-1)){//既染白又染黑 printf("NO"); return 0; } printf("YES"); return 0; }