赞
踩
假设有一个地下通道迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关。请问你如何从某个起点开始在迷宫中点亮所有的灯并回到起点?
输入格式:
输入第一行给出三个正整数,分别表示地下迷宫的节点数N(1<N≤1000,表示通道所有交叉点和端点)、边数M(≤3000,表示通道数)和探索起始节点编号S(节点从1到N编号)。随后的M行对应M条边(通道),每行给出一对正整数,分别是该条边直接连通的两个节点的编号。
输出格式:
若可以点亮所有节点的灯,则输出从S开始并以S结束的包含所有节点的序列,序列中相邻的节点一定有边(通道);否则虽然不能点亮所有节点的灯,但还是输出点亮部分灯的节点序列,最后输出0,此时表示迷宫不是连通图。
由于深度优先遍历的节点序列是不唯一的,为了使得输出具有唯一的结果,我们约定以节点小编号优先的次序访问(点灯)。在点亮所有可以点亮的灯后,以原路返回的方式回到起点。
输入样例1:
6 8 1
1 2
2 3
3 4
4 5
5 6
6 4
3 6
1 5
输出样例1:
1 2 3 4 5 6 5 4 3 2 1
输入样例2:
6 6 6
1 2
1 3
2 3
5 4
6 5
6 4
输出样例2:
6 4 5 4 6 0
tips:
用递归,再外开一个栈(因为退回的时候要输出),注意:回去的时候,要先从栈顶退出自己,再输出此时的栈顶。(不然就输出了两个自己了(一个入栈时的自己一个出栈时的自己))
我的答案:
#include <iostream> #include <cstring> #include <stack> using namespace std; const int N = 1002; int n, m, src; int g[N][N]; int vis[N]; stack<int> stk; void dfs(int a) { vis[a] = 1; if (a == src) cout << a; else cout << ' ' << a; stk.push(a); for (int i = 1;i <= n;i++) { if (!vis[i] && g[a][i] == 1) dfs(i); } stk.pop(); if (!stk.empty()) cout << ' ' << stk.top(); } int main() { memset(vis, 0, sizeof(vis)); cin >> n >> m >> src; int s, d; for (int i = 0;i < m;i++) { cin >> s >> d; g[s][d] = g[d][s] = 1; } dfs(src); bool connected = true; for (int i = 1;i <= n;i++) { if (!vis[i]) connected = false; } if (!connected) cout <<' '<< 0; }
“六度空间”理论又称作“六度分隔(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%
最终答案:
#include <iostream> #include <cstring> #include <iomanip> #include <queue> using namespace std; const int N = 1002; int n, m; int g[N][N]; int vis[N]; int bfs(int a)//从点a开始广搜 { memset(vis, 0, sizeof(vis)); int cnt=1;//六步之内能到的人数(包括自己) int layer=0;//步数 queue<int> qu; //啊啊啊啊这个不能写在函数外面,因为退出循环时栈里可能还有一层 qu.push(a); vis[a] = 1; int last = a,tail, tmp; //last:上一层最后一个节点,初始化为开始节点 //tail为当前层最后一个节点,每轮tmp不断更新tail while (!qu.empty()&&layer<6) { tmp = qu.front(); qu.pop(); for (int i = 1;i <= n;i++) { if (!vis[i] && g[tmp][i] == 1) { vis[i] = 1; qu.push(i); cnt++; tail = i; } } if (tmp == last)//当tmp为上一轮最后即为last时,tail即为当前层最后一个节点,此时更新layer { layer++; last = tail;//这一层已访问完毕,这一层已变为下一层的上一层 } } return cnt; } int main() { memset(vis, 0, sizeof(vis)); cin >> n >> m ; int s, d; for (int i = 0;i < m;i++) { cin >> s >> d; g[s][d] = g[d][s] = 1; } for (int i = 1;i <= n;i++) { int cnt = bfs(i); cout << i << ": " << fixed << setprecision(2) << cnt * 100.0 / n << '%'<<endl; } }
(一道挺简单的题目)
输入样例:
9 14
1 2
1 3
1 4
2 3
3 4
4 5
4 6
5 6
5 7
5 8
6 7
6 8
7 8
7 9
3 3 4 9
输出样例:
Cc(3)=0.47
Cc(4)=0.62
Cc(9)=0.35
Tips:
法一:dijkstra
法二:bfs 。因为无权重的图,可以用bfs求最短路径,层数就是最短步数。在题目7-2基础上,把当前layer+1赋给dis[i]。
法一答案:
#include <iostream> #include <cstring> #include <iomanip> using namespace std; #define INF 0x3f3f3f3f const int N = 1001;//不要被题目中的10000骗了,设为1001就能过,否则会内存超限 int n, m; int g[N][N]; int vis[N]; int dis[N]; void dijkstra(int src) { memset(dis, INF, sizeof(dis)); memset(vis, 0, sizeof(vis)); dis[src] = 0; for (int j = 1;j <= n;j++) { int mindis = INF, minvex; for (int i = 1;i <= n;i++) { if (!vis[i] && dis[i] < mindis) { mindis = dis[i]; minvex = i; } } vis[minvex] = 1; for (int i = 1;i <= n;i++) { if (!vis[i] && dis[i] > dis[minvex] + g[minvex][i]) { dis[i] = dis[minvex] + g[minvex][i]; } } } } int main() { memset(g, INF, sizeof(g)); cin >> n >> m; int s, d; for (int i = 1;i <= m;i++) { cin >> s >> d; g[s][d] = g[d][s] = 1; } int cnt, vex; cin >> cnt; for (int i = 0;i < cnt;i++) { cin >> vex; dijkstra(vex); int sum = 0; for (int j = 1;j <= n;j++) { sum += dis[j]; } cout << "Cc(" << vex << ")=" << fixed << setprecision(2) << (n - 1) * 1.00 / sum <<endl; } }
法二答案:
#include <iostream> #include <cstring> #include <iomanip> #include <queue> using namespace std; #define INF 0x3f3f3f3f const int N = 1001; int n, m; int g[N][N]; int vis[N]; int dis[N]; void bfs(int a)//从点a开始广搜 { memset(dis, INF, sizeof(dis)); //一开始没写这个,然后非连通图过不了 memset(vis, 0, sizeof(vis)); int layer = 0;//步数 queue<int> qu; //啊啊啊啊这个不能写在函数外面,因为退出循环时栈里可能还有一层 qu.push(a); dis[a] = 0;vis[a] = 1; int last = a, tail, tmp; //last:上一层最后一个节点,初始化为开始节点 //tail为当前层最后一个节点,每轮tmp不断更新tail while (!qu.empty()) { tmp = qu.front(); qu.pop(); for (int i = 1;i <= n;i++) { if (!vis[i] && g[tmp][i] == 1) { vis[i] = 1; qu.push(i); dis[i] = layer + 1; tail = i; } } if (tmp == last)//当tmp为上一轮最后即为last时,tail即为当前层最后一个节点,此时更新layer { layer++; last = tail;//这一层已访问完毕,这一层已变为下一层的上一层 } } } int main() { cin >> n >> m; int s, d; for (int i = 1;i <= m;i++) { cin >> s >> d; g[s][d] = g[d][s] = 1; } int cnt, vex; cin >> cnt; for (int i = 0;i < cnt;i++) { cin >> vex; bfs(vex); int sum = 0; for (int j = 1;j <= n;j++) { sum += dis[j]; } cout << "Cc(" << vex << ")=" << fixed << setprecision(2) << (n - 1) * 1.00 / sum << endl; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。