目录
6-1 Strongly Connected Components (25分)
题目描述
Write a program to find the strongly connected components in a digraph.
Format of functions:
void StronglyConnectedComponents( Graph G, void (*visit)(Vertex V) );
where Graph is defined as the following:
typedef struct VNode *PtrToVNode;
struct VNode {
Vertex Vert;
PtrToVNode Next;
};
typedef struct GNode *Graph;
struct GNode {
int NumOfVertices;
int NumOfEdges;
PtrToVNode *Array;
};
Here void (*visit)(Vertex V)
is a function parameter that is passed into StronglyConnectedComponents
to handle (print with a certain format) each vertex that is visited. The function StronglyConnectedComponents
is supposed to print a return after each component is found.
Sample program of judge:
#include <stdio.h>
#include <stdlib.h>
#define MaxVertices 10 /* maximum number of vertices */
typedef int Vertex; /* vertices are numbered from 0 to MaxVertices-1 */
typedef struct VNode *PtrToVNode;
struct VNode {
Vertex Vert;
PtrToVNode Next;
};
typedef struct GNode *Graph;
struct GNode {
int NumOfVertices;
int NumOfEdges;
PtrToVNode *Array;
};
Graph ReadG(); /* details omitted */
void PrintV( Vertex V )
{
printf("%d ", V);
}
void StronglyConnectedComponents( Graph G, void (*visit)(Vertex V) );
int main()
{
Graph G = ReadG();
StronglyConnectedComponents( G, PrintV );
return 0;
}
/* Your function will be put here */
Sample Input (for the graph shown in the figure):
4 5
0 1
1 2
2 0
3 1
3 2
Sample Output:
3
1 2 0
Note: The output order does not matter. That is, a solution like
0 1 2
3
is also considered correct.
代码实现
void StronglyConnectedComponents( Graph G, void (*visit)(Vertex V) ) {
int mp[MaxVertices][MaxVertices] = {0},num = G -> NumOfVertices;
int vis[MaxVertices] = {0};
for(int i = 0;i < num;i ++) {
PtrToVNode p = G -> Array[i];
while(p) {
mp[i][p -> Vert] = 1;
p = p -> Next;
}
}
for(int k = 0;k < num;k ++) {
for(int i = 0;i < num;i ++) {
for(int j = 0;j < num;j ++) {
if(mp[i][k] && mp[k][j]) mp[i][j] = 1;
}
}
}
for(int i = 0;i < num;i ++) {
if(vis[i]) continue;
visit(i);
vis[i] = 1;
for(int j = 0;j < num;j ++) {
if(!vis[j] && mp[i][j] && mp[j][i]) {
vis[j] = 1;
visit(j);
}
}
putchar('\n');
}
}
7-1 地下迷宫探索 (20分)
题目描述
假设有一个地下通道迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关。请问你如何从某个起点开始在迷宫中点亮所有的灯并回到起点?
输入格式:
输入第一行给出三个正整数,分别表示地下迷宫的节点数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
代码实现
#include<bits/stdc++.h>
using namespace std;
#define MAX 0x3f3f3f3f;
int N, M, S;
vector<vector<int> > myMap;//使用邻接矩阵,如果使用邻接表需要插入排序
vector<bool> visited;
bool first = true;
int counter = 0;
void dfs(int start) {
if (!first)
cout << ' ';
cout << start;
first = false;
counter++;
visited[start] = true;
for (int i = 1; i <= N; i++) {
if (!visited[i] && myMap[start][i]) {
dfs(i);
cout << ' ' << start;
}
}
}
int main() {
cin >> N >> M >> S;
myMap.resize(N + 1, vector<int>(N + 1));
visited.resize(N + 1);
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
myMap[i][j] = 0;
}
}
for (int i = 1; i <= N; i++) {
visited[i] = false;
}
int tmpStart, tmpEnd;
for (int i = 0; i < M; i++) {
cin >> tmpStart >> tmpEnd;
myMap[tmpStart][tmpEnd] = myMap[tmpEnd][tmpStart] = 1;
}
dfs(S);
if (counter < N) {
cout << " 0";
}
return 0;
}
7-2 六度空间 (20分)
题目描述
“六度空间”理论又称作“六度分隔(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%
代码实现
#include<bits/stdc++.h>
using namespace std;
#define MAX 0x3f3f3f3f;
int N, M;
vector<vector<int> >myMap;
vector<bool> visited;
void bfs(int start) {
int counterOfPeople = 0;
vector<int> current;
vector<int> nextLevel;
nextLevel.push_back(start);
for (int i = 0; i < 6; i++) {
current = nextLevel;
nextLevel.clear();
for (int j = 0; j < current.size(); j++) {
for (int k = 0; k < myMap[current[j]].size(); k++) {
if (!visited[myMap[current[j]][k]]) {
visited[myMap[current[j]][k]] = true;
counterOfPeople++;
nextLevel.push_back(myMap[current[j]][k]);
}
}
}
}
cout << start << ": " << fixed << setprecision(2) << (float)counterOfPeople / (float)N * 100 << '%' << endl;
}
//
//void dfs(int start,int counterOfLevel,int &counterOfPeople) {
// if (counterOfLevel == 7)return;
//
// visited[start] = true;
// counterOfPeople++;
// counterOfLevel++;
// for (int i = 0; i < myMap[start].size(); i++) {
// if (!visited[myMap[start][i]]) {
// dfs(myMap[start][i], counterOfLevel, counterOfPeople);
// }
// }
//}
int main() {
cin >> N >> M;
myMap.resize(N + 1);
visited.resize(N + 1);
int tmpStart, tmpEnd;
for (int i = 0; i < M; i++) {
cin >> tmpStart >> tmpEnd;
myMap[tmpStart].push_back(tmpEnd);
myMap[tmpEnd].push_back(tmpStart);
}
for (int i = 1; i <= N; i++) {
for (int i = 1; i <= N; i++) {
visited[i] = false;
}
int ansPeople = 0;
bfs(i);
//cout << i << ": " << fixed << setprecision(2) << (float)ansPeople / (float)N * 100 << '%' << endl;
}
return 0;
}
7-3 社交网络图中结点的“重要性”计算 (25分)
题目描述
输入样例:
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
代码实现
#include<bits/stdc++.h>
using namespace std;
#define MAX 0x3f3f3f3f;
int N, M, K;
vector<vector<int> >table;
int minInSP(vector<int> SP, vector<bool> selected) {
int res = -1, minValue = MAX;
for (int i = 1; i <= N; i++) {
if (!selected[i]&&SP[i] < minValue) {
res = i;
minValue = SP[i];
}
}
return res;
}
float dijkstra(int start) {
vector<bool> selected(N + 1);
vector<int> shortestPath(N + 1);
for (int i = 1; i <= N; i++) {
selected[i] = false;
}
selected[start] = true;
for (int i = 1; i <= N; i++) {
if (table[start][i]) {
shortestPath[i] = table[start][i];
}
else {
shortestPath[i] = MAX;
}
}
shortestPath[start] = 0;
for (int i = 1; i < N; i++) {
int min = minInSP(shortestPath,selected);
if (min == -1) {
return 0;
}
selected[min] = true;
for (int j = 1; j <= N; j++) {
if (!selected[j] && shortestPath[min] + table[min][j] < shortestPath[j]) {
shortestPath[j] = shortestPath[min] + table[min][j];
}
}
}
/*for (int i = 1; i <= N; i++) {
if (shortestPath[i] >= 0x3f3f3f3f) {
return 0;
}
}*/
float sum = 0;
for (int i = 1; i <= N; i++) {
if (i == start)continue;
sum += shortestPath[i];
}
return (float)(N - 1) / sum;
}
int main() {
cin >> N >> M;
table.resize(N + 1, vector<int>(N + 1));
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
table[i][j] = MAX;
}
}
int tmpStart, tmpEnd;
for (int i = 0; i < M; i++) {
cin >> tmpStart >> tmpEnd;
table[tmpStart][tmpEnd] = table[tmpEnd][tmpStart] = 1;
}
cin >> K;
int tmpK;
for (int i = 0; i < K; i++) {
cin >> tmpK;
cout << "Cc(" << tmpK << ")=" <<fixed<<setprecision(2)<< dijkstra(tmpK) << endl;
}
return 0;
}