“六度空间”理论又称作“六度分隔(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结合的,之前的题目是邻接矩阵+BFS,所以我搬东西的时候很晕,修修改改大概写好了调试的时候发现传统的队列函数(也是搬的)在我这里出问题了,队列里面的参数很诡异的自增,也没有赋值语句就突然+1+2的,然后我就把传统的队列换成了简陋版过了,至于思路什么的,太晕了就不注释了😵,不想再看这题了,图形还不熟悉,以后熟悉了再二刷吧。
能通过的代码(乱的很):
#include<stdio.h>
#include<stdlib.h>
#define MAXN 1001
#define MAXM 33
typedef int Vertex;
int visit[MAXN];
/* 定义邻接点的类型 ps:点和表搞清楚 */
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode
{
Vertex AdjV; /* 邻接点的下标 */
PtrToAdjVNode Next;//next啥意思还不知道?
}; //typedef写的乱主要是浙大老师写的太花了,就乱一点巩固typedef语法吧
/* 连接线的类型 */
typedef struct ENode *PtrToENode;
struct ENode{
Vertex V1,V2; /* 有向边<V1,V2> */
};
typedef PtrToENode Edge;
/* 定义邻接表类型AdjList */
typedef struct Vnode
{
PtrToAdjVNode FirstEdge;//指向第一条边结 点的指针
}AdjList[MAXN];
/* 以邻接表的方式存储的图类型 */
typedef struct GNode *PtrToGNode;//定义point to GNode的指针 PtrToGNode
struct GNode{
int Nv; /* 顶点数 */
int Ne; /* 边数 */
AdjList G;
};
typedef PtrToGNode LGraph;
/* 定义队列结构 */
typedef struct queue *PtrToQueue;
struct queue{
int Front;//列队头
int Last;// 列队尾
int Que[MAXN];//定义队列数组
};
typedef PtrToQueue Queue;
//建立邻接表
LGraph BuildGraph();
LGraph CreateGraph(int VertexNum);
void InsertEdge(LGraph Graph,Edge E);
//广度优先搜索需要先定义使用队列的基本操作
Queue CreateQueue();//创建队列
void InQueue(Queue q,Vertex v);//入队
int IsEmpty(Queue q);//判断列队是否为空
Vertex OutQueue(Queue q);//出队
//判断六度空间
void SDS(LGraph G);
int BFS(LGraph G,Vertex v);
void PrintG(LGraph G)
{
int i;
PtrToAdjVNode x;
for(i = 1; i <= G->Nv;i++){
x = G->G[i].FirstEdge;
while(x != NULL){
printf(" %d",x->AdjV);
x = x->Next;
}
printf("\n");
}
}
int main()
{
LGraph G;
int count;
Queue Q;
G = BuildGraph();
// PrintG(G);//检测图有没有问题
SDS(G);
}
/* 创建图 */
LGraph BuildGraph(){//这里的BuildGraph函数和MGraph是很相似的,这是规范命名的功劳,要养成好习惯
LGraph Graph;
Vertex V;
Edge E;
int Nv,i;
scanf("%d",&Nv);//先输入顶点数
Graph = CreateGraph(Nv);
scanf("%d",&(Graph->Ne));
if(Graph->Ne != 0){
E = (Edge)malloc(sizeof(struct ENode));
for(i=0;i<Graph->Ne;i++){
scanf("%d%d",&E->V1,&E->V2);
InsertEdge(Graph,E);
}
}
return Graph;
}
LGraph CreateGraph(int VertexNum)
{
LGraph Graph;
Vertex V;
Graph = (LGraph)malloc(sizeof(struct GNode));
Graph->Nv = VertexNum;
Graph->Ne = 0;
for( V = 1; V < VertexNum + 1; V++){
Graph->G[V].FirstEdge = NULL;//注意这里的->和.的区别, ->前面应该是一个结构体变量指针, . 的前面应该是一个结构体变量
visit[V] = 0;
}
return Graph;
}
/* 插入边 */
void InsertEdge(LGraph Graph,Edge E)
{
PtrToAdjVNode NewNode;
/*******************插入边<V1,V2>**********************/
/* 建立新的结点然后初始化 */
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV = E->V2;
/* 把新的结点插在链表头 */
NewNode->Next = Graph->G[E->V1].FirstEdge;
Graph->G[E->V1].FirstEdge = NewNode;
/*********如果是无向图就反向插入,插入边<V2,V1>*********/
/* 建立新的结点然后初始化 */
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV = E->V1;
/* 把新的结点插在链表头 */
NewNode->Next = Graph->G[E->V2].FirstEdge;
Graph->G[E->V2].FirstEdge = NewNode;
}
Queue CreateQueue()//队列的函数,不会去补习(反正我是补习了好久)
{
Queue q;
q = (Queue)malloc(sizeof(struct queue));
q->Front = 0;
q->Last = 0;
int i;
// for (i = 0; i < MAXN; i++)
// q->Que[i] = -1;
return q;
}
void InQueue(Queue q,Vertex v){
if(q->Last == MAXN -1) return;
q->Que[q->Last++] = v;
return;
return;
}
int OutQueue(Queue q)
{
if(IsEmpty(q) == 1 ) return -1;
Vertex v = q->Que[q->Front++];
return v;
}
int IsEmpty(Queue q)
{
if(q->Front == q->Last )
return 1;
else
return 0;
}
//判断六度空间
void SDS(LGraph G)
{
int count,i,j;
float n;
for(i = 1; i <= G->Nv; i++){
count = BFS(G,i)- 1;
n = (float)count / G->Nv * 100;
printf("%d: %.2f%%\n",i,n);
for(j = 1; j <= G->Nv; j++){
visit[j] = 0;
}
}
}
/* 这里注释掉的都是传统队列函数,出的错太诡异,大佬们要是有空帮弟弟康康哪错了/(ㄒoㄒ)/~~ */
int BFS(LGraph G,Vertex v)
{
int count = 1,i,level = 0,last = v,tail;
// Queue q;
PtrToAdjVNode x;
int q[MAXN];
int front = -1,rear = -1;
// q = CreateQueue();
// InQueue(q,v);
q[++rear] = v;
// while( IsEmpty(q) == 0 ){
while(front < rear){
// v = OutQueue(q);
v = q[++front];
x = G->G[v].FirstEdge;
while(x!= NULL){
if(!visit[x->AdjV]){
visit[x->AdjV] = 1;
// InQueue(q,i);
q[++rear] = x->AdjV;
count++;
tail = x->AdjV;
}
x = x->Next;
}
if( v == last){
last = tail;
level++;
}
if(level == 6) break;
}
return count;
}