小米笔试的最后一题就是图论的一道题,仔细写了一下答案,结果在gcc和vs下都测试通过:
就是一个找无向图的连通子图问题,通过图上面的dfs和bfs都可以,下面使用二维数组表示图之间的关系。
这个是vs下面的代码:
// xiaomi.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdlib.h>
#include <string.h>
static char* relations;
static char* flag;
static int num;
#define relation(a, b) *(relations + (num) * (a) + (b))
#define set_relation(a, b) relation(a, b)=1
static int alloc_mem(int n){ //分配数组的内存和标志位的内存
num = n;
flag = (char*)malloc(num);
if(!flag)
return -1;
memset(flag, 0, num);
relations = (char*)malloc(num * num);
if(!relations){
free(flag);
return -1;
}
memset(relations, 0, num * num);
return 0;
}
static void free_mem(){
free(flag);
free(relations);
}
static void add_relation(int a, int b){ //为无向图添加关联关系
set_relation(a, b);
set_relation(b, a);
}
static void dfs_graph(int root){ //dfs搜索
*(flag + root) = 1;
int iter = 0;
while(iter < num){
if(relation(root, iter) && *(flag + iter) == 0)
dfs_graph(iter);
iter ++;
}
}
static int flag_one(){ //是否所有的节点都遍历到了,如果还有节点没有被访问就返回下一个没有被访问的节点,否则返回-1
int i;
for(i = 0; i < num; i++)
if(*(flag+i) == 0)
return i;
return -1;
}
int friends(int n, int m, int r[][2]){ //计算连通子图的个数
int iter = 0, next = 0;
int friends_count = 0;
if(alloc_mem(n) == -1)
return -1;
while(iter < m){
int a = r[iter][0];
int b = r[iter][1];
add_relation(a - 1, b-1);
iter ++;
}
while((next = flag_one()) != -1){
dfs_graph(next);
friends_count++;
}
return friends_count;
}
int _tmain(int argc, _TCHAR* argv[])
{
int n = 5, m = 3;
int r[][2] = {{1, 2}, {2, 3}, {4, 5}};
printf("%d", friends(n, m, r));
free_mem();
return 0;
}