问题描述
给一个图,有N个结点 M条边 然后找出每一个结点从当前结点开始 与该节点距离不超过6的结点数占结点总数N的百分比.
题目链接:
https://pintia.cn/problem-sets/15/problems/715
数据范围:
N: 1 < N < 1e3
M: <= 33 *N
样例:
Input:
1 2 3 4 5 6 7 8 9 10
| 10 9 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10
|
Output:
1 2 3 4 5 6 7 8 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%
|
知识点
图论遍历搜索/计数问题 可采用DFS/BFS求解。
对于该题,把每一个结点的交际圈看成一层,与该节点相连的所有节点都做计数,并与该节点距离小于6的节点做计数。
BFS/DFS的选择:
每一个节点 计算与其联通的所有节点,BFS较好。
BFS模板+计数
初始的BFS模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| int BFS(int x) { memset(vis, 0, sizeof(vis)); queue<int>q; q.push(x); vis[x] = 1; while(!q.empty()) { int x = q.front(); q.pop(); for(int i = 1; i <= N; i++) { if(vis[i] == 0 && G[x][i] == 1) { vis[i] = 1; q.push(i); } } } }
|
- 对每一个节点进行BFS
- BFS中累计访问的节点数目
- 记录“层”数,只计算六层以内的节点数目(难点:如何记录层数)
BFS的记录层数写法详解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| G[maxn][maxn]:存图 vis[maxn]:标记该点是否被探索过 ?想一下把vis的memset放到BFS里?还是main里?
Count:计数距离小于6的节点 int BFS(int x) { memset(vis, 0, sizeof(vis)); queue<int>q; int Count = 1; q.push(x); vis[x] = 1; while(!q.empty()) { int x = q.front(); q.pop(); for(int i = 1; i <= N; i++) { if(vis[i] == 0 && G[x][i] == 1) { Count++; vis[i] = 1; q.push(i); } } } return Count; }
最初赋值 先令last = v; 即当前last指向该节点,然后遍历节点,压缩进队列过程中,将最后一个赋值给tail 然后如果不为空出队过程中,如果last = 出队的节点,对last 重新赋值(下一层最后一个节点->tail) int BFS(int x) { memset(vis, 0, sizeof(vis)); queue<int>q; int Count = 1; int tail; int last = x; int ans = 0; q.push(x); vis[x] = 1; while(!q.empty()) { int x = q.front(); q.pop(); for(int i = 1; i <= N; i++) { if(vis[i] == 0 && G[x][i] == 1) { Count++; vis[i] = 1; q.push(i); tail = i; } } if(last == x) { ans++; last = tail; } if(ans == 6) break; } return Count; }
|
题目做法
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #include <bits/stdc++.h> using namespace std; const int maxn = 10000 + 10; int G[maxn][maxn]; int vis[maxn]; int N, E; int BFS(int x) { memset(vis, 0, sizeof(vis)); queue<int>q; int Count = 1; int tail; int last = x; int ans = 0; q.push(x); vis[x] = 1; while(!q.empty()) { int x = q.front(); q.pop(); for(int i = 1; i <= N; i++) { if(vis[i] == 0 && G[x][i] == 1) { Count++; vis[i] = 1; q.push(i); tail = i; } } if(last == x) { ans++; last = tail; } if(ans == 6) break; } return Count; } int main(void) { cin >> N >> E; for(int i = 0; i < E; i++) { int a, b; cin >> a >> b; G[a][b] = G[b][a] = 1; }
for(int i = 1; i <= N; i++) { int sovle = BFS(i); double output = sovle * 100.0 / N; printf("%d: %.2lf%%\n", i, output); } return 0; }
|
总结点
- BFS/DFS选取可以看问题是要最近/最多/最远进行选择,一般路径最短问题DFS,路径条数问题BFS.
- memset在进行初始化中,要看数据范围,在该题,若对G进行初始化,则会发生内存超限。
参考资料
- https://www.cnblogs.com/zengguoqiang/p/8429087.html
- https://blog.csdn.net/Dream_Weave/article/details/80870033