UVA - 10004 Bicoloring(判断二分图——交叉染色法 / 带权并查集)
d.给定一个图,判断是不是二分图。
s.可以交叉染色,就是二分图;否则,不是。
另外,此题中的图是强连通图,即任意两点可达,从而dfs方法从一个点出发就能遍历整个图了。
如果不能保证从一个点出发可以遍历整个图,那么编程要注意了,应该从每个点出发遍历一次。
s2.带权并查集来判断,略复杂。先略过。先上个博客:http://blog.csdn.net/zsc09_leaf/article/details/6727622
c.邻接矩阵,bfs
#include<iostream> #include<stdio.h> #include<queue> #include<string.h> using namespace std; #define MAXN 205 int map[MAXN][MAXN]; int color[MAXN]; int n; bool bfs(int start){//bfs交叉染色,两种颜色标记为 1 和 -1,未染色标记为 0 queue<int>q; color[start]=1; q.push(start); while(!q.empty()){ int temp=q.front(); q.pop(); for(int i=0;i<n;++i){ if(map[temp][i]){ if(color[i]==0){//未染色 if(color[temp]==1){ color[i]=-1; } else{ color[i]=1; } q.push(i); } else{//已染色 if(color[i]==color[temp]){//相邻的两点颜色相同 return false;//不能交叉染色 } } } } } return true; } int main(){ int L; int u,v; while(~scanf("%d",&n)){ if(n==0)break; memset(map,0,sizeof(map)); memset(color,0,sizeof(color)); scanf("%d",&L); for(int i=0;i<L;++i){ scanf("%d%d",&u,&v); map[u][v]=1; map[v][u]=1; } if(bfs(0)){ printf("BICOLORABLE.\n"); } else{ printf("NOT BICOLORABLE.\n"); } } return 0; }
c2.邻接矩阵,dfs。这个图是强连通的,所以一次dfs可以遍历所有节点了。如果不是强连通的,则需要遍历多次。
#include<iostream> #include<stdio.h> #include<queue> #include<string.h> using namespace std; #define MAXN 205 int map[MAXN][MAXN]; int color[MAXN]; int n; bool dfs(int u){//dfs交叉染色,两种颜色标记为 1 和 -1,未染色标记为 0 for(int i=0;i<n;++i){ if(map[u][i]){ if(color[i]==0){//未染色 if(color[u]==1){ color[i]=-1; } else{ color[i]=1; } if(!dfs(i)){//不能交叉染色 return false; } } else{//已染色 if(color[i]==color[u]){//不能交叉染色 return false; } } } } return true; } int main(){ int L; int u,v; while(~scanf("%d",&n)){ if(n==0)break; memset(map,0,sizeof(map)); memset(color,0,sizeof(color)); scanf("%d",&L); for(int i=0;i<L;++i){ scanf("%d%d",&u,&v); map[u][v]=1; map[v][u]=1; } color[0]=1; if(dfs(0)){//这个图是强连通的,所以一次dfs可以遍历所有节点了。如果不是强连通的,则需要遍历多次。 printf("BICOLORABLE.\n"); } else{ printf("NOT BICOLORABLE.\n"); } } return 0; }
c3.邻接表,bfs
#include<iostream> #include<stdio.h> #include<queue> #include<string.h> using namespace std; #define MAXN 205//点数 #define MAXM 10000//边数 int color[MAXN]; struct Edge{ int to,next; }edge[MAXM]; int head[MAXN]; int tot; void addedge(int u,int v){ edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void init(){ tot=0; memset(head,-1,sizeof(head)); } bool bfs(int start){//bfs交叉染色,两种颜色标记为 1 和 -1,未染色标记为 0 int v; queue<int>q; color[start]=1; q.push(start); while(!q.empty()){ int temp=q.front(); q.pop(); for(int i=head[temp];i!=-1;i=edge[i].next){// v=edge[i].to; if(color[v]==0){//未染色 if(color[temp]==1){ color[v]=-1; } else{ color[v]=1; } q.push(v); } else{//已染色 if(color[v]==color[temp]){//相邻的两点颜色相同 return false;//不能交叉染色 } } } } return true; } int main(){ int n,L; int u,v; while(~scanf("%d",&n)){ if(n==0)break; memset(color,0,sizeof(color)); init(); scanf("%d",&L); for(int i=0;i<L;++i){ scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } if(bfs(0)){ printf("BICOLORABLE.\n"); } else{ printf("NOT BICOLORABLE.\n"); } } return 0; }
c4.邻接表,dfs
#include<iostream> #include<stdio.h> #include<queue> #include<string.h> using namespace std; #define MAXN 205//点数 #define MAXM 10000//边数 int color[MAXN]; struct Edge{ int to,next; }edge[MAXM]; int head[MAXN]; int tot; void addedge(int u,int v){ edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void init(){ tot=0; memset(head,-1,sizeof(head)); } bool dfs(int u){//dfs交叉染色,两种颜色标记为 1 和 -1,未染色标记为 0 int v; for(int i=head[u];i!=-1;i=edge[i].next){ v=edge[i].to; if(color[v]==0){//未染色 if(color[u]==1){ color[v]=-1; } else{ color[v]=1; } if(!dfs(v)){//不能交叉染色 return false; } } else{//已染色 if(color[v]==color[u]){//不能交叉染色 return false; } } } return true; } int main(){ int n,L; int u,v; while(~scanf("%d",&n)){ if(n==0)break; memset(color,0,sizeof(color)); init(); scanf("%d",&L); for(int i=0;i<L;++i){ scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } color[0]=1; if(dfs(0)){ printf("BICOLORABLE.\n"); } else{ printf("NOT BICOLORABLE.\n"); } } return 0; }