六度空间 06-图3 六度空间(30 分)

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

六度空间
06-图3 六度空间(30 分)
图1 六度空间示意图

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

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

输入格式:

输入第1行给出两个正整数,分别表示社交网络图的结点数N(1<N104​​,表示人数)、边数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%

本来编程时,结果如下

测试点提示结果耗时内存

0 sample 简单一条链 答案正确 2 ms 372KB
1 不连通 答案正确 2 ms 384KB
2 一般图 答案正确 2 ms 372KB
3 最小N和M 答案正确 2 ms 368KB
4 最大N和M 答案错误 1069 ms 2628KB
后在一位童鞋的帮助下:

有点在回想我当初做这道题时,有哪些坑被我踩过。。这个BFS根据last来判断是否结束的时候,出现了问题。目前是,如果发现一个点没被访问,就入队,然后直到它被访问,如果它刚好是下一个level的最后一个元素,碰到它了就认为这一层结束了。但是,一个结点是可能多次入队的,比如2和3都是目前这一层,4都是它的子节点,那么4就会入队两次,但不能一碰到4就认为下一层结束。所以在if(!visited)里,就做个访问标记,这样的话别的父节点就不能使它入队了。似乎我之前查这道题答案时还有看到节点里有level的解法。

成功解决了该问题;改后结果如下:

测试点提示结果耗时内存

0 sample 简单一条链 答案正确 2 ms 368KB
1 不连通 答案正确 3 ms 372KB
2 一般图 答案正确 2 ms 368KB
3 最小N和M 答案正确 2 ms 372KB
4 最大N和M 答案正确 515 ms 2540KB

 1 #include<iostream>
 2 
 3 #include<vector>
 4 #include<queue>
 5 #include<iomanip>
 6 using namespace std;
 7 #define maxvertexnum 10006
 8 #define vertex int
 9 vector<int> enqueue(maxvertexnum,0);
10 vector<int> visited(maxvertexnum,0);
11 struct adjnode{
12 vertex v;
13 adjnode* next;
14 };
15 using ptrtoadjnode=adjnode*;
16 struct edge{
17 vertex v1,v2;
18 };
19 using Edge=edge*;
20 struct vnode{
21 ptrtoadjnode firstedge;
22 };
23 using adjlist=vnode[maxvertexnum];
24 struct  graph{
25 int Nv;
26 int Ne;
27 adjlist G;
28 };
29 using Graph=graph*;
30 void Insert(Graph gra,Edge e){
31     ptrtoadjnode newnode=new adjnode();
32 newnode->v=e->v2;
33 newnode->next=gra->G[e->v1].firstedge;
34 gra->G[e->v1].firstedge=newnode;
35 newnode=new adjnode();
36 newnode->v=e->v1;
37 newnode->next=gra->G[e->v2].firstedge;
38 gra->G[e->v2].firstedge=newnode;
39 }
40 Graph BuildGraph(){
41 vertex v;
42 Graph gra=new graph();
43 Edge e=new edge();
44 cin>>gra->Nv>>gra->Ne;
45 for(v=1;v<=gra->Nv;v++)
46     gra->G[v].firstedge=NULL;
47 for(v=0;v<gra->Ne;v++){
48   cin>>e->v1>>e->v2;
49   Insert(gra,e);
50 }
51 return gra;
52 }
53 int BFS(Graph gra,vertex v){
54 queue<int> Q; int cnt=1; vertex v2; ptrtoadjnode ptr;
55 int last=v,tail,level=0;
56 Q.push(v); 
57 visited[v]=1;
58 while(!Q.empty()){
59 v=Q.front();
60 Q.pop();
61 visited[v]=1;
62     ptr=gra->G[v].firstedge;
63     while(ptr){
64     v2=ptr->v;
65     ptr=ptr->next;
66 if(visited[v2]!=1&&enqueue[v2]==0){
67 Q.push(v2); enqueue[v2]=1; cnt++;
68 tail=v2;}
69 }
70 if(last==v){
71 ++level; last=tail;
72 }
73 if(level==6) 
74 break;
75 }
76 for(auto &o:visited)
77 o=0;
78 for(auto &o:enqueue)
79         o=0;
80 return cnt;
81 }
82 void SDS(Graph gra){
83 vertex v;  double cnt;
84 for(v=1;v<=gra->Nv;v++){
85 cnt=BFS(gra,v);
86 cnt=cnt/gra->Nv*100;
87 //cout<<v<<":"<<" "<<setiosflags(ios::fixed)
88 //<<setprecision(2)<<cnt<<"%"<<endl;
89 cout<<v<<":"<<" ";
90     printf("%.2lf",cnt);
91 cout<<"%"<<endl;
92 }
93 }
94 int main(){
95 Graph gra=BuildGraph();
96 SDS(gra);
97 return 0;
98 }
View Code

非常开心在同学的帮助下解开了心结