zoukankan      html  css  js  c++  java
  • 06-图3 六度空间 (30分)

    题目描述

    “六度空间”理论又称作“六度分隔(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题,我们只需对每一个顶点BFS,统计每次BFS能在六圈之内访问的顶点数即可。

    代码

    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAXSIZE 1001
    
    //邻接矩阵实现图
    struct Graph {
        int vertexCount;    //顶点数
        int edgeCount;      //边数
        int matrix[MAXSIZE][MAXSIZE];   //邻接矩阵
    };
    typedef struct Graph *MGraph;
    
    struct QNode {
        int data;
        struct QNode *next;
    };
    typedef struct QNode *Queue;
    
    int visited[MAXSIZE] = {0};
    
    MGraph createGraph(int N, int M);
    void SDS(MGraph graph);
    int BFS(MGraph graph, int vertex);
    Queue createQueue();
    void pushQueue(Queue queue, int data);
    int popQueue(Queue queue);
    
    int main() {
        int N, M;
        scanf("%d %d", &N, &M);
        MGraph graph = createGraph(N, M);
        SDS(graph);
        return 0;
    }
    
    //创建图
    MGraph createGraph(int N, int M) {
        MGraph graph = (MGraph) malloc(sizeof(struct Graph));
        graph->vertexCount = N;
        graph->edgeCount = M;
        for (int i = 0; i <= N; i++) {
            for (int j = 0; j <= N; j++) {
                graph->matrix[i][j] = 0;
            }
        }
        for (int i = 0; i < M; i++) {
            int v1, v2;
            scanf("%d %d", &v1, &v2);
            graph->matrix[v1][v2] = 1;
            graph->matrix[v2][v1] = 1;
        }
        return graph;
    }
    
    //解决六度空间问题,对每个顶点BFS统计六度之内的顶点数
    void SDS(MGraph graph) {
        for (int i = 1; i <= graph->vertexCount; i++) {     //需要注意是从下标为1开始的
            int count = BFS(graph, i);
            printf("%d: %.2lf%%
    ", i, count * 1.0 / graph->vertexCount * 100);
            for (int j = 1; j <= graph->vertexCount; j++) {     //每BFS完一个顶点重置访问数组
                visited[j] = 0;
            }
        }
    }
    
    //BFS,主要逻辑与常规BFS相同,但需要控制在六圈之内
    int BFS(MGraph graph, int vertex) {
        int count = 1, level = 0, last = vertex;    //last是当前层的最后一个顶点
        int tail = 0;   //tail是下一层的最后一个顶点
        Queue queue = createQueue();
        pushQueue(queue, vertex);
        visited[vertex] = 1;
        while (queue->next) {
            vertex = popQueue(queue);
            for (int i = 1; i <= graph->vertexCount; i++) {
                if (!visited[i] && graph->matrix[vertex][i]) {
                    pushQueue(queue, i);
                    count++;            //count要在入队时加一,若在出队时加一会漏掉最外面一圈
                    visited[i] = 1;
                    tail = i;
                }
            }
            //若出队的顶点是当前层的最后一个顶点
            if (vertex == last) {
                level++;
                if (level == 6) return count;
                last = tail;
            }
        }
        return count;
    }
    
    //创建队列,返回链表哨兵结点
    Queue createQueue() {
        Queue queue = (Queue) malloc(sizeof(struct QNode));
        queue->data = -1;
        queue->next = NULL;
        return queue;
    }
    
    //尾插法入队
    void pushQueue(Queue queue, int data) {
        Queue rear = queue;
        while (rear->next) rear = rear->next;
        Queue newNode = (Queue) malloc(sizeof(struct QNode));
        newNode->data = data;
        newNode->next = NULL;
        rear->next = newNode;
    }
    
    //删除链表首结点
    int popQueue(Queue queue) {
        if (!queue->next) return -1;
        Queue deleteNode = queue->next;
        int ret = deleteNode->data;
        queue->next = deleteNode->next;
        free(deleteNode);
        return ret;
    }
    
  • 相关阅读:
    【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 15—Anomaly Detection异常检测
    【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 14—Dimensionality Reduction 降维
    【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 13—Clustering 聚类
    【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 12—Support Vector Machines 支持向量机
    【原】机器学习公开课 目录(课程笔记、测验习题答案、编程作业源码)...持续更新...
    【原】Coursera—Andrew Ng机器学习—Week 11 习题—Photo OCR
    【原】Coursera—Andrew Ng机器学习—Week 10 习题—大规模机器学习
    【原】Coursera—Andrew Ng机器学习—Week 9 习题—异常检测
    【原】Coursera—Andrew Ng机器学习—Week 8 习题—聚类 和 降维
    【原】Coursera—Andrew Ng机器学习—Week 7 习题—支持向量机SVM
  • 原文地址:https://www.cnblogs.com/AndyHY-Notes/p/12582882.html
Copyright © 2011-2022 走看看