06-图3 六度空间 (30 分) ,BFS的变形应用

“六度空间”理论又称作“六度分隔(Six Degrees of Separation)”理论。这个理论可以通俗地阐述为:“你和任何一个陌生人之间所间隔的人不会超过六个,也就是说,最多通过五个人你就能够认识任何一个陌生人。”如图1所示。

在这里插入图片描述

“六度空间”理论虽然得到广泛的认同,并且正在得到越来越多的应用。但是数十年来,试图验证这个理论始终是许多社会学家努力追求的目标。然而由于历史的原因,这样的研究具有太大的局限性和困难。随着当代人的联络主要依赖于电话、短信、微信以及因特网上即时通信等工具,能够体现社交网络关系的一手数据已经逐渐使得“六度空间”理论的验证成为可能。

假如给你一个社交网络图,请你对每个节点计算符合“六度空间”理论的结点占结点总数的百分比。

输入格式:
输入第1行给出两个正整数,分别表示社交网络图的结点数N(1<N≤10
3
,表示人数)、边数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%
结尾无空行

这题主要考察的是BFS的一个变形,在这里,广度优先遍历并不需要全部遍历完全,根据六度空间理论,只需要遍历六层就可以了,难就难在怎么确定是在第六层。
因为广度优先遍历进队列和出队列的是否都是按照顺时针(或者逆时针)顺序进行的,所以把每一层最后一个进行相邻结点进队列操作的结点设置为last,然后与上面进行相邻结点进队列操作的结点w进行比较,如果相等,说明w所在这一层的每一个结点都已经进行的相邻结点进队列的操作,那么这一层以及遍历完全了,那么level++;同时用temp放入进队列循环里面去,用以找到last。然后当level==6时就可以break了
代码如下:

#include<iostream>
#include<iomanip>
using namespace std;
typedef int ElemType;
const int MaxSize = 1001;
int A[MaxSize][MaxSize] = { 0 };
//队列的定义及运算
typedef struct {
	ElemType data[MaxSize];
	int front, rear;
}SqQueue;
void InitQueue(SqQueue*& q)
{
	q = new SqQueue;
	q->front = q->rear = 0;
}
void DestoryQueue(SqQueue*& q)
{
	delete q;
}
bool QueueEmpty(SqQueue* q)
{
	return(q->front == q->rear);
}
bool enQueue(SqQueue*& q, ElemType e)
{
	if ((q->rear + 1) % MaxSize == q->front)
		return false;
	q->rear = (q->rear + 1) % MaxSize;
	q->data[q->rear] = e;
	return true;
}
bool deQueue(SqQueue*& q, ElemType& e)
{
	if (q->front == q->rear)
		return false;
	q->front = (q->front + 1) % MaxSize;
	e = q->data[q->front];
	return true;
}
//邻接表存储方法
typedef struct Node {
	int adjvex;//结点编号
	struct Node* nextarc;//指向下一个边结点
}ArcNode;//边结点类型
typedef struct node {
	ElemType datal;
	ArcNode* firstarc;//头指针指向第一个边结点
}VNode;//头结点类型
typedef struct node1 {
	VNode adjlist[MaxSize];
	int n, e;
}AdjGraph;//图邻接表类型
//创建图邻接表
void CreateAdj(AdjGraph*& G, int A[MaxSize][MaxSize], int n)
{
	ArcNode* p;
	G = new AdjGraph;
	for (int i = 1;i <= n;++i)
		G->adjlist[i].firstarc = NULL;
	for(int i=1;i<=n;++i)
		for (int j = n;j > 0;--j)
			if (A[i][j])
			{
				p = new ArcNode;
				p->adjvex = j;
				p->nextarc = G->adjlist[i].firstarc;
				G->adjlist[i].firstarc = p;
			}
	G->n = n;
}
//广度优先遍历算法的变形
int BFS(AdjGraph* G, int v)
{
	int level = 0, last = v,ans=1,temp=0;
	int Visited[MaxSize] = { 0 };
	int w;ArcNode* p;
	SqQueue* qu;
	InitQueue(qu);
	enQueue(qu, v);
	Visited[v] = 1;
	while (!QueueEmpty(qu))
	{
		deQueue(qu, w);
		p = G->adjlist[w].firstarc;
		while (p != NULL)
		{
			if (!Visited[p->adjvex])
			{
				Visited[p->adjvex] = 1;
				enQueue(qu, p->adjvex);
				ans++;//用来记录访问过的结点数
				temp = p->adjvex;
			}
			p = p->nextarc;
		}
		if (last == w)
		{
			level++;last = temp;//这里当last=temp是把该层的最后一个访问的结点放在last里面
			//当该层最后一个结点w的周围元素进行了进栈操作之后,会有此时的w=last,表示该层
			//的所有元素也全部操作完成,此时level++;
		}
		if (level == 6)break;
	}
	return ans;
}
int main()
{
	//int A[MaxSize][MaxSize] = { 0 };放入全局里面了,否在栈溢出
	int N, M;
	cin >> N >> M;
	int temp1, temp2;
	for (int i = 1;i <= M;++i)
	{
		cin >> temp1 >> temp2;
		A[temp1][temp2] = 1;
		A[temp2][temp1] = 1;
	}
	AdjGraph* G;
	CreateAdj(G, A, N);
	for (int i = 1;i <= N;++i)
	{
		int ans = BFS(G, i);
		double answer = ans, N1 = N;
		double s = (answer*100) / N1;
		cout << i << ": " << setprecision(2) << fixed << s <<"%"<< endl;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值