列表

详情


OR142. 二分图判定

描述

给定一个由n个点,m条边组成的无向图(注意,此图可能不连通),对任意1 ≤ i ≤ m存在一条边连接u[i], v[i]。回答此图是不是二分图。二分图定义为存在一种给图中每一个点染上黑白两色其中之一的着色方式,使得对每一对有边直接相连的点颜色不同。 

输入描述

第一行输入为N和M,代表无向图的点数和边数。

接下来M行,表示M条边,每一行两个整数u[i], v[i],满足1 ≤ u[i], v[i] ≤ n,保证图中无重边,自环。

其中保证1 ≤ N, M ≤ 100000

输出描述

一行字符串,为Yes,或者No。

Yes表示输入图是二分图。

No表示输入图不是二分图。

示例1

输入:

5 7
1 2
2 3
3 4
4 1
4 5
5 2

输出:

Yes

说明:

如图,把1, 3, 5点染色为白,2, 4染色为黑,即可满足二分图要求,所以这个图是二分图。

示例2

输入:

5 4
1 2
2 3
3 1
4 5

输出:

No

说明:

1, 2, 3号点无论如何染色都无法满足要求,所以不是二分图。

原站题解

C 解法, 执行用时: 1ms, 内存消耗: 372KB, 提交时间: 2020-05-20

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10001
typedef int Vertex;
typedef int WeightType;
typedef struct GNode *PtrToGNode;
struct GNode{
    int N;
    int Ne;
    WeightType G[MAXSIZE][MAXSIZE];
};
typedef PtrToGNode MGraph;
      
int color=0;
int flag=1;
      
MGraph ReadG();
void dfs(MGraph Graph,int cur,int color);
int swap(int color);
int known[MAXSIZE]={0};
int Color[MAXSIZE]={-1};
      
      
int main(){
    MGraph Graph;
    int i;
    Graph=ReadG();
    Color[0]=1;
    known[0]=1;
    dfs(Graph,1,0);
    if(flag==1) printf("Yes\n");
    else printf("No\n");
    //for(i=0;i<Graph->N;i++){
    //  printf("known[%d]=%d\n Color[%d]=%d\n",i,known[i],i,Color[i]);
    //}
}
      
      
MGraph ReadG(){
    MGraph P;
    int i,j,k;
    int m,n;
          
    P=(MGraph)malloc(sizeof(struct GNode));
      
    scanf("%d%d",&P->N,&P->Ne);
      
    for(i=1; i<=P->N; i++) {
        for(j=1; j<=P->N; j++) {
            P->G[i][j]=-1;
        }
    }
     
      
    for(i=0;i<P->Ne;i++){
        scanf("%d%d",&m,&n);
        P->G[m][n]=1;
    }
     
         
          
    return P;
}
      
void dfs(MGraph Graph,int cur,int color){
    int i;
    if(flag==0) return;
    if(known[cur]==1){
        if(Color[cur]!=color){
            //printf("color%d:error\n");
            flag=0;
        }
        return;
    }
    else{
        Color[cur]=color;
        known[cur]=1;
        //printf("color%d:%d\n",cur,color);
    }
    for(i=1;i<=Graph->N;i++){
        if(Graph->G[cur][i]==1){
        //  printf("%d to %d\n",cur,i);
            dfs(Graph,i,swap(color));
            if(flag==0) return;
        }
    }
          
    return;
}
      
int swap(int color){
    if(color==0) color=1;
    else color=0;
    return color;
}

C 解法, 执行用时: 2ms, 内存消耗: 368KB, 提交时间: 2021-07-17

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef enum { UNKNOWN = 0, BLACK = 1, WHITE = 2 } Color;

typedef struct {
  int to;
  int next;
} Edge;

void addEdge(int* head, Edge* edges, int u, int v, int i) {
  (*(edges + i)).next = *(head + u);
  (*(edges + i)).to = v;
  *(head + u) = i;
}

void printAdjList(int* head, Edge* edges, const int n) {
  int i, u;
  for (u = 1; u <= n; ++u) {
    fprintf(stdout, "vertex %d: [ ", u);
    for (i = *(head + u); i; i = (*(edges + i)).next)
      fprintf(stdout, "%d ", (*(edges + i)).to);
    fputs("]\n", stdout);
  }
  fputc(10, stdout);
}

int dfs(int* head, Edge* edges, int curr, Color color, Color* colors) {
  *(colors + curr) = color;
  int i, nei;
  for (i = *(head + curr); i; i = (*(edges + i)).next) {
    nei = (*(edges + i)).to;
    if (*(colors + nei) == color) return 0; // 我邻居的颜色与我相同,表明存在着冲突
    if (*(colors + nei) == UNKNOWN && 
        !dfs(head, edges, nei, color == BLACK ? WHITE : BLACK, colors))
      return 0;
  }
  return 1;
}

int main(const int argc, const char* argv[]) {
  int n, m, u, v;
  fscanf(stdin, "%d %d", &n, &m);
  
  int head[n + 1]; 
  Edge edges[m << 1 | 1];
  memset(head, 0x0000, sizeof head);
  
  int i = 0;
  while (m--) {
    fscanf(stdin, "%d %d", &u, &v);
    addEdge(head, edges, u, v, ++i);
    addEdge(head, edges, v, u, ++i);
  }
  
  Color colors[n + 1];
  memset(colors, UNKNOWN, sizeof colors);
  
  // 图中可能有多个连通分量 (连通分量 == 极大的连通子图)
  for (u = 1; u <= n; ++u)
    if (*(colors + u) == UNKNOWN && !dfs(head, edges, u, BLACK, colors))
      return fputs("No", stdout), 0;
  
  return fputs("Yes", stdout), 0;
}

上一题