7-2 六度空间(30 分)
“六度空间”理论又称作“六度分隔(Six Degrees of Separation)”理论。这个理论可以通俗地阐述为:“你和任何一个陌生人之间所间隔的人不会超过六个,也就是说,最多通过五个人你就能够认识任何一个陌生人。”如图1所示。
图1 六度空间示意图
“六度空间”理论虽然得到广泛的认同,并且正在得到越来越多的应用。但是数十年来,试图验证这个理论始终是许多社会学家努力追求的目标。然而由于历史的原因,这样的研究具有太大的局限性和困难。随着当代人的联络主要依赖于电话、短信、微信以及因特网上即时通信等工具,能够体现社交网络关系的一手数据已经逐渐使得“六度空间”理论的验证成为可能。
假如给你一个社交网络图,请你对每个节点计算符合“六度空间”理论的结点占结点总数的百分比。
输入格式:
输入第1行给出两个正整数,分别表示社交网络图的结点数N(1<N≤104,表示人数)、边数M(≤33×N,表示社交关系数)。随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个结点的编号(节点从1到N编号)。
输出格式:
对每个结点输出与该结点距离不超过6的结点数占结点总数的百分比,精确到小数点后2位。每个结节点输出一行,格式为“结点编号:(空格)百分比%”。
输入样例:
10 9
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
输出样例:
1: 70.00%
2: 80.00%
3: 90.00%
4: 100.00%
5: 100.00%
6: 100.00%
7: 100.00%
8: 90.00%
9: 80.00%
10: 70.00%
#include<stdio.h> #include<malloc.h> #define MAX 10001//最大顶点数 /** *解题思想: *对图进行广度搜索 *得出每层中的顶点数 *计算百分比 */ int BFS(int i, int N, int ** snap) {// 队列 遍历登记 队头 队尾 计数器 层数 int q[MAX], visit[MAX], front, rear, count, level, last, tail, v, j; for (j = 0; j < 10001; j++)//初始化数组 visit[j] = 0; visit[i] = 1;//开始结点 front = rear = -1;//队列初始化 count = 1;//计算六度空间的个数 level = 0;//level计算层数,等于6时跳出 last = i;//last为上一层最后的顶点 q[++rear] = i;//入队 当前顶点所在层数 while (front<rear) //遍历队列(六层以内) { /* *图的广度搜索原理解析: *类似二叉树的层序遍历 *1、从所需要的顶点进入图(类似利用此顶点为树的根结点,构建一棵树) *2、根结点入队列 *3、寻找与此顶点相连的所有顶点并放入队列中(图的临接矩阵中,储存的是每个顶点间的边的关系,而且无向图的临接矩阵一定为对称矩阵) *4、当顶点所在行遍历结束,取出队列的下一个顶点,重复。直至遍历所有的顶点 */ v = q[++front]; //出队 for (j = 1; j <= N; j++)//遍历 if (!visit[j] && snap[v][j] == 1) {//当结点没有记录而且此处结点为顶点时 q[++rear] = j;//入队列 visit[j] = 1;//记录对应位置 count++;//计数器 tail = j;//tail是当前层的最后一个顶点 } if (v == last) { level++;//层数加一 last = tail;//记录最后一个顶点 } if (6 == level)//等于六层时,退出循环 break; } return count;//返回六度空间内所有顶点数 } int main(void) { int N, M; int count = 0; scanf("%d %d", &N, &M); int **snap;//实现动态分配二维数组 /*注意: *******动态分配必须按照顺序分配 *******同时数组释放内存的时候要按照先后顺序释放 *******否则会出现野指针 *******内存泄漏导致程序崩溃 */ snap = (int**)malloc(sizeof(int*) * (N + 1)); if (snap == NULL) return -1; //动态分配内存存在失败的可能,所以 //在进行动态分配内存后 //应该进行对应的指针是否为空指针的判断 int i, x, y, j; for (i = 0; i <= N; i++) { *(snap + i) = (int *)malloc(sizeof(int) * (N + 1)); if (*(snap + i) == NULL) return -1; } for (i = 0; i < M; i++) { scanf("%d %d", &x, &y);//无向图对角线对称 snap[x][y] = snap[y][x] = 1;//关系对等 } for (i = 1; i <= N; i++) { count = BFS(i, N, snap); printf("%d: %.2f%%\n", i, (float)count / N * 100); } //直接进行头指针的内存释放不全等于所有指针内存的释放 //free(snap); for (i = 0; i < N; i++) { free(*(snap + i)); *(snap + i) = NULL; } free(snap); snap = NULL; return 0; }