二分图程序一直false

来源:4-11 实现二分图检测

慕用0058068

2020-12-30

老师,我用C改写了,但一直 false,不知道是那部分不对。

bool __isBipartite( adjMatrix *G, int *colors, int i )
{
    for (int j = 0; j < G->n; j++) {                   // 遍历顶点 i 所有相邻的点
        if ( G->matrix[i][j] != 0 && colors[G->matrix[i][j]] == 0 ) {                 // 如果当前邻点没有访问过
             colors[G->matrix[i][j]] = (colors[i]== 'r' ? 'b' : 'r');    
            // 若当前邻点的颜色是 'r'(红色),改为 'b'(蓝色),否则 'r'(红色)  --> 保证顶点 v 和顶点 v 所有相邻点的颜色不同
            if ( !__isBipartite(G, colors, G->matrix[i][j]) ) 
            // 如果 __isBipartite 值为false,就不是二分图
                return false;
            
        } else if ( G->matrix[i][j] != 0 &&   colors[G->matrix[i][j]] == colors[i] )
                return false;
              // 颜色相同,出现矛盾
       }

    return true;
}

bool isBipartite( adjMatrix *G )
{
    int *colors = malloc(sizeof(int) * MAX_vertex);
    memset(colors, 0, sizeof(int) * MAX_vertex);

    for (int i = 0; i < G->n; i++) {
        if (colors[i] == 0) {    // colors 当做标记数组 visited,等于0 表示还没访问
            colors[i] = 'r';     // 标记为已访问,并标记为 'r'(红色)
            if ( !__isBipartite(G, colors, i) ) {
                // 如果 __isBipartite 值为false,就不是二分图
                 return false;
            }
        }
    }
    
    free(colors); colors = NULL; // 防止野指针
    return true;
}

测试代码(测试部分是正确的):

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef enum
{								// 枚举图类型
	DG = 1,						// 有向无权图
	DN = 2,						// 无向无权图
	UDG = 3,					// 有向有权图
	UDN = 4						// 无向无权图
} graph_kind;

/* 邻接矩阵 */
typedef int T;
typedef struct graph_adj_matrix
{
	T *list;					// 顶点表,存储顶点本身的数据,如顶点1的信息是[北京]
	int **matrix;				// 二维数组
	int n;						// 顶点数
	int m;						// 弧数
	graph_kind kind;			// 图的类型
} adjMatrix;

#define MAX_vertex 256			// 最大顶点数
#define MAX_edge  MAX_vertex * MAX_vertex
	// 最大弧数,邻接矩阵的空间是 
											// n*n
											
											
/* 获取顶点的位置 */
int vertices_pos(adjMatrix * G, T v)
{
	for (int i = 0; i < G->n; i++)
		if (G->list[i] == v)
			return i;

	return -1;					// 找不到,v不存在
}

void create_graph(adjMatrix * G)
{
	/* 存储顶点信息 */
	G->list = (T *) malloc(sizeof(T) * MAX_vertex);
	assert(G->list != NULL);

	G->matrix = (int **)malloc(sizeof(int) * MAX_vertex);
	// 先开辟行

	for (int i = 0; i < MAX_vertex; i++)	// 再开辟列
		G->matrix[i] = (int *)malloc(sizeof(int) * MAX_edge);

	/* 初始化矩阵 */
	for (int i = 0; i < MAX_vertex; i++)
		for (int j = 0; j < MAX_edge; j++)
			G->matrix[i][j] = 0;

	/* 顶点、弧的数据,从文件里读出来 */
	puts("请输入测试文件:> ");
	char file_name[128] = "";
	scanf("%127[^\n]", file_name);
	FILE *fp = fopen(file_name, "r");
	assert(fp);

	fscanf(fp, "%d%*c%d", &(G->n), &(G->m));
	scanf("%*[^\n]"), scanf("%*c");	// 清空缓冲区

	puts("\n请输入顶点信息:)");
	for (int i = 0; i < G->n; i++)
	{
		scanf("%[a-z-A-Z0-9]%*c", &G->list[i]);	// 读取数据(只能是字母和数字),并消除数据之外的字符
	}

	while (puts("\n请选择图(1有向图, 2无向图, 3有向网, 4无向网:)"),
		   scanf("%d", &G->kind), !(G->kind >= 1 && G->kind <= 4)
		   // n个逗号表达式的值是最后一个,刚好可以结合循环做结束条件,如果输入值不是 
		   // 1、2、3、4,就一直输入
		);

	T v1, v2;
	int w;
	switch (G->kind)
	{
	case DG:
		for (int i = 0; i < G->m; i++)
		{
			while (fgetc(fp) != '\n');	// 文件指针移动到下一行
			fscanf(fp, "%c %c", &v1, &v2);
			int n = vertices_pos(G, v1);
			int m = vertices_pos(G, v2);
			assert(m != -1);	// 顶点 v1 不存在
			assert(n != -1);

			G->matrix[n][m] = 1;
		}
		break;

	case DN:
		for (int i = 0; i < G->m; i++)
		{
			while (fgetc(fp) != '\n');	// 文件指针移动到下一行
			fscanf(fp, "%c %c", &v1, &v2);
			int n = vertices_pos(G, v1);
			int m = vertices_pos(G, v2);
			assert(m != -1);
			assert(n != -1);

			G->matrix[n][m] = 1;
			G->matrix[m][n] = 1;	// 无向图的二阶矩阵沿主对角线对称
		}
		break;

	case UDG:
		for (int i = 0; i < G->m; i++)
		{
			while (fgetc(fp) != '\n');	// 文件指针移动到下一行
			fscanf(fp, "%c %c %d", &v1, &v2, &w);
			int n = vertices_pos(G, v1);
			int m = vertices_pos(G, v2);
			assert(m != -1);
			assert(n != -1);

			G->matrix[n][m] = w;
		}
		break;

	case UDN:
		for (int i = 0; i < G->m; i++)
		{
			while (fgetc(fp) != '\n');	// 文件指针移动到下一行
			fscanf(fp, "%c %c %d", &v1, &v2, &w);
			int n = vertices_pos(G, v1);
			int m = vertices_pos(G, v2);
			assert(m != -1);
			assert(n != -1);

			 G->matrix[n][m] = w;
			G->matrix[m][n] = w;
		}
		break;

	default:
		break;
	}
}


int main()
{
	adjMatrix G;
	// 建模图:邻接矩阵

	create_graph(&G);
	// 构造图:图建模[邻接矩阵]、初始化矩阵、构造某种类型图、读入测试数据
	
	isBipartite(&G)?puts("此图是二分图\n") : puts("此图不是二分图");
	// 测试二分图的函数
	return 0;
}
写回答

2回答

liuyubobobo

2020-12-30

对不起,你这样给我一片代码,我也不能帮你调试。你需要自己找到一个小的,可以反映出这段代码错误的测试用例,去调试跟踪,看你的代码的每一步执行结果是怎样的,和你的预期是否相符,为什么应该是 true 的二分图,最终还是返回了 false,具体是哪一步出现了错误。


进步就在这个过程中。


加油!:)

0
1
慕用0058068
非常感谢!
2020-12-30
共1条回复

慕用0058068

提问者

2020-12-31

true
4 4
0 1
0 3
1 2
2 3
false
4 6
0 1
0 2
0 3
1 2
1 3
2 3


0
1
慕用0058068
第一组算例是 true,第二组算例是 false
2020-12-31
共1条回复

玩转算法系列--图论精讲(Java版)

30+小时系统学习,bobo带你克服被图论支配的恐惧

1591 学习 · 324 问题

查看课程