博客作业06--图
1.学习总结
1.1图的思维导图
1.2 图结构学习体会
图的遍历的定义:
从图的某个顶点出发访问遍图中所有顶点,且每个顶点仅被访问一次。(连通图与非连通图)
深度优先遍历(DFS);
1、访问指定的起始顶点;
2、若当前访问的顶点的邻接顶点有未被访问的,则任选一个访问之;反之,退回到最近访问过的顶点;直到与起始顶点相通的全部顶点都访问完毕;
3、若此时图中尚有顶点未被访问,则再选其中一个顶点作为起始顶点并访问之,
广度优先遍历(BFS)
方法:从图的某一结点出发,首先依次访问该结点的所有邻接顶点 Vi1, Vi2, …, Vin 再按这些顶点被访问的先后次序依次访问与它们相邻接的所有未被访问的顶点,重复此过程,直至所有顶点均被访问为止。
Prim算法的实现过程
首先以一个结点作为最小生成树的初始结点,然后以迭代的方式找出最小生成树中各结点权重最小的边,并加到最小生成树中。(加入之后如果产生回路了就要跳过这条边,选择下一个结点。)当所有的结点都加入到最小生成树中后,就找出了这个连通图的最小生成树。
Kruskal算法
Kruskal算法在找最小生成树结点之前,需要对权重从小到大进行排序。将排序好的权重边依次加入到最小生成树中,(如果加入时产生回路就跳过这条边,加入下一条边)。当所有的结点都加入到最小生成树中后,就找到了这个连通图的最小生成树。
Dijkstra算法
1、令arcs表示弧上的权值。若弧不存在,则置arcs为∞(在本程序中为MAXCOST)。S为已找到的从 出发的的终点的集合,初始状态为空集。那么,从 出发到图上其余各顶点 可能达到的长度的初值为D=arcs[Locate Vex(G, )], ∈V;
2、选择 ,使得D =Min{ D | ∈V-S } ;
3、修改从 出发的到集合V-S中任一顶点 的最短路径长度
拓扑排序
在有向图中选一个没有前驱的顶点并且输出
从图中删除该顶点和所有以它为尾的弧(白话就是:删除所有和它有关的边)
重复上述两步,直至所有顶点输出,或者当前图中不存在无前驱的顶点为止,后者代表我们的有向图是有环的,因此,也可以通过拓扑排序来判断一个图是否有环。
2.PTA实验作业
2.1 题目1:7-1 图着色问题
2.2 设计思路
定义整型变量v, e, k;
定义整型数组map[501][501] = {0};
定义整型数组color[501] = {0};来储存颜色
bool flag = true;
bool vis[501];
/*void isYes(int i) {
if (vis[i] || flag == false) {
return;
}
vis[i] = true;
for (int j = 0; j < v; j++) {
if (color[i] == color[j] && map[i][j] == 1) {
flag = false;
return;
} else if (map[i][j] == 1 && vis[j] == false){
isYes(j);
}
}
}*/
int main()
{
输入v e k;
for (定义整型变量i 当i小于e时执行循环) {
定义循环变量 x, y存放边端点;
输入 x y;
x--;
y--;
map[x][y] = 1;
map[y][x] = 1;
}
定义整型变量m储存待检查边数;
输入m;
for (当i<m时执行循环) {
//set<int> s;
for ( j = 0; j小于顶点数v时执行循环) {
输入此端点的颜色
s.insert(c);
color[j] = c;
}
如果(s.size() != k) {
将变量flag=-1;
}
否则 {
memset(vis, false, sizeof(vis));
如果 (flag==1) {
输出yes 并换行
} 否则{
输出no并换行
}
}
}
2.3 代码截图
2.4 PTA提交列表说明
提交时答案错误是因为对颜色是否相同的判断不是很严谨所以导致的的答案错误,修改后更正
2.1 题目2:7-2 排座位
2.2 设计思路
定义整形数组 f[101];
int main(){
定义整形变量 n,m,k,a,b,c,d,e;
定义整形数组arr[101][101];
进行初始化
输入 n m k
for(ii = 1;i <= n时执行循环)
f[i] = i;
while(m--){
scanf("%d%d%d",&a,&b,&c);输 a b c
if(如果是敌人)
arr[a][b] = arr[b][a] = -1标记
else
//如果不是敌人,并查集进行合并,因为朋友的朋友也是朋友
}
while(k--){//朋友的朋友也是朋友
scanf("%d%d",&d,&e);
if(如果d和e是朋友,并且没有敌对关系){//
printf("No problem\n");
继续循环
}
if(//如果d和e不是朋友,并且没有敌对关系{
printf("OK\n");
继续循环
}
if(如果d和e是朋友,并且有敌对关系){//
printf("OK but...\n");
继续循环
}
if(如果d和e不是朋友,并且有敌对关系){//
printf("No way\n");
继续循环
}
}
}
2.3 代码截图
2.4 PTA提交列表说明
前几次提交都是因为判断函数void merge(int x,int y)中的递归调用出错了导致很多情况判断不出来,后经仔细修改后更正。
2.1 题目3:7-3 六度空间
2.2 设计思路
int BFS(int i, int N, int ** snap)
{
定义整型变量 q[MAX], visit[MAX], front, rear, count, level, last, tail, v, j;
for ()//初始化数组
visit[j] = 0;
visit[i] = 1开始结点
队列初始化
计算六度空间的个数 并储存再count中
level计算层数,等于6时跳出
last = i;last为上一层最后的顶点
i入队 当前顶点所在层数
while (front<rear) //遍历队列(六层以内)
{
//出队
for (j)//遍历
if (当结点没有记录而且此处结点为顶点时)
{//
j入队列
记录对应位置
计数器 递增
tail = j;//tail是当前层的最后一个顶点
}
if (v == last)
{
//记录最后一个顶点
}
if (6 == level)//等于六层时,退出循环
break;
}
return count;//返回六度空间内所有顶点数
}
2.3 代码截图