问题 : 算法7-4,7-5:图的遍历——深度优先搜索
时间限制: 1 Sec 内存限制: 32 MB
提交: 12 解决: 12
[提交][状态]
题目描述
深度优先搜索遍历类似于树的先根遍历,是树的先根遍历的推广。其过程为:假设初始状态是图中所有顶点未曾被访问,则深度优先搜索可以从图中的某个顶点v出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作为起始点,重复上述过程,直至图中所有顶点都被访问到为止。
在本题中,读入一个无向图的邻接矩阵(即数组表示),建立无向图并按照以上描述中的算法遍历所有顶点,输出遍历顶点的顺序。
输入
输入的第一行包含一个正整数n,表示图中共有n个顶点。其中n不超过50。
以后的n行中每行有n个用空格隔开的整数0或1,对于第i行的第j个0或1,1表示第i个顶点和第j个顶点有直接连接,0表示没有直接连接。当i和j相等的时候,保证对应的整数为0。
输入保证邻接矩阵为对称矩阵,即输入的图一定是无向图。
输出
只有一行,包含n个整数,表示按照题目描述中的深度优先遍历算法遍历整个图的访问顶点顺序。每个整数后输出一个空格,并请注意行尾输出换行。
样例输入
4
0 1 0 1
1 0 0 0
0 0 0 1
1 0 1 0
样例输出
0 1 3 2
模板:
# include <stdio.h>
# include <string.h>
int a[51][51], book[51];
int n;
void dfs(int cur)
{
printf("%d ", cur);
if (cur == n)
return;
int k;
for (k = 0; k < n; k ++)
{
if (a[cur][k] == 1 && book[k] == 0)
{
book[k] = 1;
dfs(k);
}
}
return;
}
int main(void)
{
int i ,j;
while (~ scanf("%d", &n))
{
for (i = 0; i < n; i ++)
for (j = 0; j < n; j ++)
scanf("%d", &a[i][j]);
memset(book, 0, sizeof(book));
book[0] = 1;
dfs(0);
}
return 0;
}
问题 : 算法7-6:图的遍历——广度优先搜索
时间限制: 1 Sec 内存限制: 32 MB
提交: 13 解决: 10
[提交][状态]
题目描述
广度优先搜索遍历类似于树的按层次遍历的过程。其过程为:假设从图中的某顶点v出发,在访问了v之后依次访问v的各个未曾被访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作为起始点。重复上述过程,直至图中所有顶点都被访问到为止。
其算法可以描述如下:
在本题中,读入一个无向图的邻接矩阵(即数组表示),建立无向图并按照以上描述中的算法遍历所有顶点,输出遍历顶点的顺序。
输入
输入的第一行包含一个正整数n,表示图中共有n个顶点。其中n不超过50。
以后的n行中每行有n个用空格隔开的整数0或1,对于第i行的第j个0或1,1表示第i个顶点和第j个顶点有直接连接,0表示没有直接连接。当i和j相等的时候,保证对应的整数为0。
输入保证邻接矩阵为对称矩阵,即输入的图一定是无向图。
输出
只有一行,包含n个整数,表示按照题目描述中的广度优先遍历算法遍历整个图的访问顶点顺序。每个整数后输出一个空格,并请注意行尾输出换行。
样例输入
4
0 0 0 1
0 0 1 1
0 1 0 1
1 1 1 0
样例输出
0 3 1 2
模板:
# include <stdio.h>
# include <string.h>
int a[51][51], qwe[1501], book[51];
int main(void)
{
int t, c, i, j;
while (~ scanf("%d", &t))
{
memset(book, 0, sizeof(book));
memset(qwe, 0, sizeof(qwe));
for (i = 0; i < t; i ++)
for (j = 0; j < t; j ++)
scanf("%d", &a[i][j]);
int head = 0, tail = 0;
qwe[tail] = 0;
tail ++;
book[0] = 1;
int cur, k;
while (head < tail && tail < t)
{
cur = qwe[head];
for (k = 0; k < t; k ++)
{
if (a[cur][k] == 1 && book[k] == 0)
{
qwe[tail] = k;
tail ++;
book[k] = 1;
}
if (tail >= t)
break;
}
head ++;
}
for (i = 0; i < tail; i ++)
printf("%d ", qwe[i]);
printf("\n");
}
return 0;
}
问题 : 算法7-9:最小生成树
时间限制: 1 Sec 内存限制: 32 MB
提交: 7 解决: 6
[提交][状态]
题目描述
最小生成树问题是实际生产生活中十分重要的一类问题。假设需要在n个城市之间建立通信联络网,则连通n个城市只需要n-1条线路。这时,自然需要考虑这样一个问题,即如何在最节省经费的前提下建立这个通信网。
可以用连通网来表示n个城市以及n个城市之间可能设置的通信线路,其中网的顶点表示城市,边表示两个城市之间的线路,赋于边的权值表示相应的代价。对于n个顶点的连通网可以建立许多不同的生成树,每一棵生成树都可以是一个通信网。现在,需要选择一棵生成树,使总的耗费最小。这个问题就是构造连通网的最小代价生成树,简称最小生成树。一棵生成树的代价就是树上各边的代价之和。
而在常用的最小生成树构造算法中,普里姆(Prim)算法是一种非常常用的算法。以下是其算法的大致结构:
在本题中,读入一个无向图的邻接矩阵(即数组表示),建立无向图并按照以上描述中的算法建立最小生成树,并输出最小生成树的代价。
输入
输入的第一行包含一个正整数n,表示图中共有n个顶点。其中n不超过50。
以后的n行中每行有n个用空格隔开的整数,对于第i行的第j个整数,如果不为0,则表示第i个顶点和第j个顶点有直接连接且代价为相应的值,0表示没有直接连接。当i和j相等的时候,保证对应的整数为0。
输入保证邻接矩阵为对称矩阵,即输入的图一定是无向图,且保证图中只有一个连通分量。
输出
只有一个整数,即最小生成树的总代价。请注意行尾输出换行。
样例输入
4
0 2 4 0
2 0 3 5
4 3 0 1
0 5 1 0
样例输出
6
模板:
# include <stdio.h>
# include <string.h>
int main(void)
{
int t, a[51][51], book[51], dis[51];
while (~ scanf("%d", &t))
{
memset(book, 0, sizeof(book));
int i, j;
for (i = 1; i <= t; i ++)
for (j = 1; j <= t; j ++)
{
scanf("%d", &a[i][j]);
if(i != j && a[i][j] == 0)
a[i][j] = 99999999;
}
int count = 0, sum = 0;
book[1] = 1;
count ++;
int min;
for (i = 1; i <= t; i ++)
dis[i] = a[1][i];
while (count < t)
{
min = 99999999;
for (i = 1; i <= t; i ++)
{
if (book[i] == 0 && dis[i] < min)
{
min = dis[i];
j = i;
}
}
book[j] = 1;
count ++;
sum += dis[j];
for (int k = 1; k <= t; k ++)
{
if (book[k] == 0 && dis[k] > a[j][k])
dis[k] = a[j][k];
}
}
printf("%d\n", sum);
}
return 0;
}