其他分享
首页 > 其他分享> > 7-7 六度空间 (30 分)

7-7 六度空间 (30 分)

作者:互联网

7-7 六度空间 (30 分)

题目链接:
https://pintia.cn/problem-sets/15/problems/715

问题描述:

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

在这里插入图片描述

图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题,我们可以用邻接表的方式来存储各个点之间的连接关系。然后对每个点进行广度优先遍历,计算距离与当前结点距离不超过6的结点个数。
示例的邻接表:
在这里插入图片描述

代码:

代码中已经有详细的注释,就不过多赘述。

#include<bits/stdc++.h>
using namespace std;
vector<int> G[10005];   //邻接表
int vis[10005];
int cnt;

int BFS(int num){
    queue<int> Q;   //用于存储当前所在的结点
    Q.push(num);    //以第num结点为起点,所以把num结点存进队列
    for(int deep = 0; deep < 6; deep++){    //以起点为第一层,寻找能6步以内到达的结点
        vector<int> v;  //动态数组用于存储当前所在的所有结点
        while(Q.size() > 0){    //把当前的所有结点存进动态数组
            v.push_back(Q.front());
            Q.pop();
        }
        for(int i=0; i < v.size(); i++){    //把当前所在的所有结点全部遍历,寻找能从它们其中任何一个结点开始一步之内就能到达的下一个结点
            int x = v[i];   //用一个新的变量存储当前所在的所有结点的其中一个结点
            for(int j = 0; j < G[x].size(); j++){   //通过邻接表即可快速找到当前结点一步之内可以到达的结点
                if(vis[G[x][j]] == 0){  //判断当前结点一步之类能到达的下一个结点是否到达过
                    cnt++;  //如果没有,那么6步之内能到达的结点数+1
                    vis[G[x][j]] = 1;   //并把该点设置为到达过
                    Q.push(G[x][j]);    //把该点加入当前所在的结点队列,因为下一次循环要寻找从这个结点起一步之内能到达的其他结点
                }
            }
        }
    }
}

int main(){
    int a, b;
    scanf("%d%d", &a, &b);
    while( b -- ){  //记录结点之间边的关系,利用邻接表
        int x, y;
        scanf("%d%d", &x, &y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    for(int i=1; i <= a; i++){
        cnt = 0;    //每次更换起点都需要把6步之内能到达的结点数归零
        memset(vis, 0, sizeof(vis));    //把记录结点是否到达过的数组归零
        BFS(i); //把当前结点作为起点,计算距离为6的结点数
        double ans = cnt * 1.0/ a;  //计算出答案
        printf("%d: %.2f%%\n", i, ans * 100);   //输出结果
    }
}

标签:结点,六度,int,30,到达,vis,push,空间
来源: https://blog.csdn.net/qq_46213352/article/details/116998123