• 06-图3 六度空间


    广度优先搜索

      之前把图的邻接矩阵和邻接表都写了一下,所以这题做起来挺轻松的。

    解题思路:

      这题顶点的数量很大,边较少,所以采用邻接表来实现了。

      用tail记录最后进队的元素,last = tail记录该层tail的值。当last出队时代表层数++;

      count用来记录六度空间内的顶点数。

      

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


    图1 六度空间示意图

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

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

    输入格式:

    输入第1行给出两个正整数,分别表示社交网络图的结点数NN(1<Nle 10^41<N104​​,表示人数)、边数MM(le 33 imes N33×N,表示社交关系数)。随后的MM行对应MM条边,每行给出一对正整数,分别是该条边直接连通的两个结点的编号(节点从1到NN编号)。

    输出格式:

    对每个结点输出与该结点距离不超过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%

      1 //顶点数众多 而边数少 故采用邻接表 
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <cstdlib> 
      5 #include <queue>
      6 using namespace std;
      7 
      8 #define MaxVertexNum 10000    /* 最大顶点数设为100 */
      9 typedef int Vertex;         /* 用顶点下标表示顶点,为整型 */
     10 typedef int WeightType;        /* 边的权值设为整型 */
     11 typedef char DataType;        /* 顶点存储的数据类型设为字符型 */
     12   
     13 /* 边的定义 */
     14 typedef struct ENode *PtrToENode;
     15 struct ENode{
     16     Vertex V1, V2;      /* 有向边<V1, V2> */
     17 };
     18 typedef PtrToENode Edge;
     19   
     20 /* 邻接点的定义 */
     21 typedef struct AdjVNode *PtrToAdjVNode; 
     22 struct AdjVNode{
     23     Vertex AdjV;        /* 邻接点下标 */
     24     PtrToAdjVNode Next;    /* 指向下一个邻接点的指针 */
     25 };
     26   
     27 /* 顶点表头结点的定义 */
     28 typedef struct Vnode{
     29     PtrToAdjVNode FirstEdge;/* 边表头指针 */
     30 } AdjList[MaxVertexNum];    /* AdjList是邻接表类型 */
     31   
     32 /* 图结点的定义 */
     33 typedef struct GNode *PtrToGNode;
     34 struct GNode{  
     35     int Nv;     /* 顶点数 */
     36     int Ne;     /* 边数   */
     37     AdjList G;  /* 邻接表 */
     38 };
     39 typedef PtrToGNode LGraph; /* 以邻接表方式存储的图类型 */
     40 bool Visited[MaxVertexNum] = {false}; 
     41 
     42 LGraph CreateGraph( int VertexNum );
     43 void InsertEdge( LGraph Graph, Edge E );
     44 LGraph BuildGraph();
     45 void Visit( Vertex V );
     46 void InitVisited();
     47 int BFS( LGraph Graph, Vertex V, void (*Visit)(Vertex) );
     48 
     49 LGraph CreateGraph( int VertexNum )
     50 { /* 初始化一个有VertexNum个顶点但没有边的图 */
     51     Vertex V;
     52     LGraph Graph;
     53       
     54     Graph = (LGraph)malloc( sizeof(struct GNode) ); /* 建立图 */
     55     Graph->Nv = VertexNum;
     56     Graph->Ne = 0;
     57     /* 初始化邻接表头指针 */
     58     /* 注意:这里默认顶点编号从0开始,到(Graph->Nv - 1) */
     59        for (V=0; V<Graph->Nv; V++)
     60         Graph->G[V].FirstEdge = NULL;
     61               
     62     return Graph; 
     63 }
     64          
     65 void InsertEdge( LGraph Graph, Edge E )
     66 {
     67     PtrToAdjVNode NewNode;
     68       
     69     /* 插入边 <V1, V2> */
     70     /* 为V2建立新的邻接点 */
     71     NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
     72     NewNode->AdjV = E->V2;
     73     /* 将V2插入V1的表头 */
     74     NewNode->Next = Graph->G[E->V1].FirstEdge;
     75     Graph->G[E->V1].FirstEdge = NewNode;
     76           
     77     /* 若是无向图,还要插入边 <V2, V1> */
     78     /* 为V1建立新的邻接点 */
     79     NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
     80     NewNode->AdjV = E->V1;
     81     /* 将V1插入V2的表头 */
     82     NewNode->Next = Graph->G[E->V2].FirstEdge;
     83     Graph->G[E->V2].FirstEdge = NewNode;
     84 }
     85   
     86 LGraph BuildGraph()
     87 {
     88     LGraph Graph;
     89     Edge E;
     90     Vertex V;
     91     int Nv, i;
     92       
     93     scanf("%d", &Nv);   /* 读入顶点个数 */
     94     Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */ 
     95       
     96     scanf("%d", &(Graph->Ne));   /* 读入边数 */
     97     if ( Graph->Ne != 0 ) { /* 如果有边 */ 
     98         E = (Edge)malloc( sizeof(struct ENode) ); /* 建立边结点 */ 
     99         /* 读入边,格式为"起点 终点",插入邻接矩阵 */
    100         for (i=0; i<Graph->Ne; i++) {
    101             scanf("%d %d", &E->V1, &E->V2); 
    102             InsertEdge( Graph, E );
    103         }
    104     } 
    105   
    106     return Graph;
    107 }
    108 
    109 //初始化 Visited[] = false
    110 void InitVisited()
    111 {
    112     for(int i = 0; i < MaxVertexNum; i++)
    113         Visited[i] = false;
    114 }  
    115 
    116 int BFS( LGraph Graph, Vertex V)
    117 {
    118     queue<Vertex> Q;     
    119     Vertex W;
    120     int count = 1;
    121     int level = 0;
    122     Vertex last = V,tail;
    123     Visited[V] = true; /* 标记V已访问 */
    124     Q.push(V);
    125     
    126     while( !Q.empty() ) {
    127         W = Q.front();
    128         Q.pop();
    129         for(PtrToAdjVNode tempV = Graph->G[W].FirstEdge; tempV; tempV=tempV->Next ) /* 对W的每个邻接点tempV->AdjV */
    130             if( !Visited[tempV->AdjV]) {
    131                 Visited[tempV->AdjV] = true;
    132                 Q.push(tempV->AdjV);
    133                 count++;
    134                 tail = tempV->AdjV;
    135             }
    136         if(W == last) {
    137             level++;
    138             last = tail;
    139         }
    140         if(level == 6)
    141             break;
    142     }
    143     return count;
    144 }
    145 
    146 
    147 int main()
    148 {
    149     LGraph graph;
    150     graph = BuildGraph();
    151     for(int i = 1; i <= graph->Nv; i++) {
    152         InitVisited();
    153         int count = BFS(graph, i);
    154         printf("%d: %.2f%%
    ",i,count*100.0/graph->Nv);
    155     }
    156     return 0;
    157 }
     
  • 相关阅读:
    Java中用JXL导出Excel代码详解
    oracle之FUNCTION拙见
    oracle 存储过程详细介绍(创建,删除存储过程,参数传递等)1
    Crontab使用方式
    Git使用技巧(3)-- 远程操作
    Git使用技巧(2)-- 基本操作
    Git使用技巧(1)-- 配置【持续更新】
    Vim使用技巧(1) -- 普通模式技巧 【持续更新】
    sublime使用技巧(4)-- 其他技巧【持续更新】
    sublime使用技巧(3)-- 常用快捷键【持续更新】
  • 原文地址:https://www.cnblogs.com/kuotian/p/5376383.html
Copyright © 2020-2023  润新知