二分图程序一直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回答
-
对不起,你这样给我一片代码,我也不能帮你调试。你需要自己找到一个小的,可以反映出这段代码错误的测试用例,去调试跟踪,看你的代码的每一步执行结果是怎样的,和你的预期是否相符,为什么应该是 true 的二分图,最终还是返回了 false,具体是哪一步出现了错误。
进步就在这个过程中。
加油!:)
012020-12-30 -
慕用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
012020-12-31
相似问题