题目:
“六度空间”理论又称作“六度分隔(Six Degrees of Separation)”理论。这个理论可以通俗地阐述为:“你和任何一个陌生人之间所间隔的人不会超过六个,也就是说,最多通过五个人你就能够认识任何一个陌生人。”如图1所示。
“六度空间”理论虽然得到广泛的认同,并且正在得到越来越多的应用。但是数十年来,试图验证这个理论始终是许多社会学家努力追求的目标。然而由于历史的原因,这样的研究具有太大的局限性和困难。随着当代人的联络主要依赖于电话、短信、微信以及因特网上即时通信等工具,能够体现社交网络关系的一手数据已经逐渐使得“六度空间”理论的验证成为可能。
假如给你一个社交网络图,请你对每个节点计算符合“六度空间”理论的结点占结点总数的百分比。
输入格式
输入第1行给出两个正整数,分别表示社交网络图的结点数N(1<N≤103,表示人数)、边数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层以内所能遍历到的结点个数
难点:判断当前层数
解决办法:增加3个变量。level记录当前层数、last指向当前层的最后一个元素(当队列pop出的元素与last相等时,说明下一层已经统计完毕,需要更新level) 、tail下一层入队结点的瞬时值(当层数更新时,为last提供在下一层的位置)
代码实现
int main()
{
int N,E;
scanf("%d%d",&N,&E);
LGraph G=CreatGraph(N);
BuildGraph(G,E);
SixDegreesSeparation(G);
return 0;
}
BFS:从V结点开始统计6层以内遍历到的结点数
int BFS(LGraph G,Vertex V)
{
int *visited=(int*)malloc(sizeof(int)*(G->VertexNum+1));
int i,j;
for(i=0;i<=G->VertexNum;i++){
visited[i]=0;
}
int *queue=(int*)malloc(sizeof(int)*(G->VertexNum));
int rear=-1,head=-1;
int level=0,last=V,tail=0;
int count=1;
visited[V]=1;
queue[++rear]=V;
while(rear>head){
V=queue[++head];
PtrToAdjVNode W=G->GList[V].FirstAdjVNode;
for(;W;W=W->Next){
if(visited[W->Adj]==0){
count++;
visited[W->Adj]=1;
queue[++rear]=W->Adj;
tail=W->Adj;
}
}
if(V==last){
level++;
last=tail;
}
if(level==6)break;
}
free(visited);
free(queue);
return count;
}
void SixDegreesSeparation(LGraph G)
{
Vertex i=1;
int count=0;
for(i=1;i<=G->VertexNum;i++){
count=BFS(G,i);
printf("%d: %.2lf%%\n",i,count*100.0/G->VertexNum);
}
}
邻接表的基础操作
#define MAXVERTEXNUM 1001
typedef int Vertex;
typedef struct AdjVNode* PtrToAdjVNode;
struct AdjVNode{
Vertex Adj;
PtrToAdjVNode Next;
};
typedef struct HNode{
PtrToAdjVNode FirstAdjVNode;
}AdjList[MAXVERTEXNUM];
typedef struct GNode* LGraph;
struct GNode{
int VertexNum;
int EdgeNum;
AdjList GList;
};
struct ENode{
Vertex V;
Vertex W;
};
typedef struct ENode* Edge;
LGraph CreatGraph(int N)
{
LGraph G=(LGraph)malloc(sizeof(struct GNode));
G->VertexNum=N;
G->EdgeNum=0;
int i;
for(i=1;i<N;i++){
G->GList[i].FirstAdjVNode=NULL;
}
return G;
}
void Insert(LGraph Graph,Edge L)
{
PtrToAdjVNode VNode=(PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
VNode->Adj=L->W;
VNode->Next=Graph->GList[L->V].FirstAdjVNode;
Graph->GList[L->V].FirstAdjVNode=VNode;
PtrToAdjVNode WNode=(PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
WNode->Adj=L->V;
WNode->Next=Graph->GList[L->W].FirstAdjVNode;
Graph->GList[L->W].FirstAdjVNode=WNode;
}
void BuildGraph(LGraph Graph,int edgeNum)
{
int i;
Graph->EdgeNum=edgeNum;
Edge L=(Edge)malloc(sizeof(struct ENode));
for(i=0;i<edgeNum;i++){
scanf("%d%d",&(L->V),&(L->W));
Insert(Graph,L);
}
}