1.本周学习总结(0--2分)
1.思维导图
2.谈谈你对图结构的认识及学习体会。
- 本周学习了图结构,图结构相对来说内容还是比较多的,但是相比较树我觉得其实更简单清晰一点 。主要图中很多算法包括如解决最小生成树问题的Prime、Kruskal算法,最短路径的Dijkstra、Floy算法等略微有点复杂,代码量也比较大。图与之前学习的树也有很大的联系。需要我们融汇贯通,课后认真巩固。
- 图的储存结构分为邻接表和邻接矩阵,我觉得邻接矩阵更好用一点,结构体也比较简单。图形结构属于复杂的非线性数据结构,在实际应用中很多问题可以用图来描述。在图结构中,每个元素可以有零个或多个前驱元素,也可以有零个或多个后继元素,也就是说元素之间的关系是多对多的。无论多么复杂的图都是由顶点和边构成的,所以定义时,图结构由两个集合点和边构成。图的存储方法为邻接矩阵和邻接表,前者引用数组,后者引用指针,所以两者在不同算法上有着自己的优势。图的遍历分为广度优先遍历BFS和深度优先遍历DFS,当在一个不带权图中搜索从一个顶点到另一个顶点的一条路径时,DFS求出的路径不一定时最短路径,而BFS求出的路径一定是最短路径。
2.2.题目1:7-1 图着色问题 (25 分)
图着色问题是一个著名的NP完全问题。给定无向图G=(V,E),问可否用K种颜色为V中的每一个顶点分配一种颜色,使得不会有两个相邻顶点具有同一种颜色?
但本题并不是要你解决这个着色问题,而是对给定的一种颜色分配,请你判断这是否是图着色问题的一个解。
2.1.1设计思路
int main()
{
MGraph g;
定义color[502],flag=0,num=0;
定义 v,e,k,n,i,j;
输入 v,e,k;
Create(g,v,e);//创建邻接矩阵
输入方案个数n;
while(n--)
{
int visited[502]={0};
num=0;flag=0;
for i=1 to i<=g.n
{
输入color[i];
if(visited[color[i]]==0)
{
visited[color[i]]=1;
num++;
}
end if
}
end for
if(num!=k)
flag=1;
for i=1 to i<=g.n
for j=1 to j<g.n
{
if(g.edges[i][j]==1&&color[i]==color[j])
{
flag=1;
break;
}
if(flag==1)
break;
}
end for
if(flag)
cout<<"No"<<endl;
else
cout<<"Yes"<<endl;
return 0;
}
void Create(MGraph &g,int v,int e)//建立邻接矩阵
{
定义i,j,k;
定义 a,b;
定义vexs[500];
for i=1 to i<=v
vexs[i]=1;
for j=0 to j<e
{
输入 a,b;
g.edges[a][b]=1;
g.edges[b][a]=1;
}
end for
g.e=e,g.n=v;
}
2.1.2.代码截图
2.1.3本题PTA提交列表说明。
- Q1:没看清题目是必须方案中颜色个数与给定k相同,导致错误
- A1:加入代码哦判断方案方案个数与k值,不同则输出错误
- Q2:写这题的时候总是出现最大图的测试点过不去,猜测是范围不够大的原因
- A2:将color[501]改为color[502]
2.2.题目2:六度空间
“六度空间”理论又称作“六度分隔(Six Degrees of Separation)”理论。这个理论可以通俗地阐述为:“你和任何一个陌生人之间所间隔的人不会超过六个,也就是说,最多通过五个人你就能够认识任何一个陌生人。”如图1所示。
图1 六度空间示意图
“六度空间”理论虽然得到广泛的认同,并且正在得到越来越多的应用。但是数十年来,试图验证这个理论始终是许多社会学家努力追求的目标。然而由于历史的原因,这样的研究具有太大的局限性和困难。随着当代人的联络主要依赖于电话、短信、微信以及因特网上即时通信等工具,能够体现社交网络关系的一手数据已经逐渐使得“六度空间”理论的验证成为可能。
假如给你一个社交网络图,请你对每个节点计算符合“六度空间”理论的结点占结点总数的百分比。
2.2.1设计思路(伪代码)
定义全局变量 数组map[10001][10001];
定义全局变量 count;
int main()
{
定义 n,m;
输入 n m;
定义i,a,b;
for i=0 to i<m
{
输入a,b;
map[a][b]=1;
map[b][a]=1;
} //建邻接矩阵
end for
for i=1 to i<=n
{
count=1;
BFS(i,n);//广度遍历
输出i:;
定义浮点数 answer;
answer=(float)count/n*100;
输出answer;
}
end for
}
void BFS(int x,int n)
{
定义变量 level=0;
定义变量 last,tail;
last=x;//存放该层的最后一个顶点
定义数组 visited[10001]={0};
visited[x]=1;
定义队列 q;
x进队列q;
while(队列q不为空)
{
取队头元素
q出队
for j=1 to j<=n
{
if(visited[j]==0&&map[x][j]==1)
{
visited[j]=1;
count++;
j进队q;
tail=j;
}
end if
}
end for
if(x==last)//为该层最后一个元素
{
level++;//层数加一
last=tail;
}
end if
if(level==6)
{
break;
}
end if
}
}
2.2.2代码截图
2.2.3本题PTA提交列表说明。
- 这题刚开始没有什么思路,后来老师在上课的时候说这道题用广度遍历做,加上找了一下这道题的代码,就自己按照思路和老师说的写了。其中模仿的网上的代码运用了tail和last控制层数,用last,tail分别记录当前层数的最后一个元素、下一层最后一个元素,从而控制层数在六层内。统计这些结点个数。当last等于队头元素时,表示进入下一层,level加一,last修改为tail,当level的值达到6,提前退出循环。
2.3.题目3.公路村村通
现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。
2.3.1设计思路
int prim()
{
fill(d,d+N,inf);
d[1]=0;
定义 ans=0;
for int i=1 to i<=n
{
定义 u=-1;
定义 min=inf;
for int j=1 to j<=n
{
if(vis[j]==false&&d[j]<min)
{
u=j;
min=d[j];
}
}
end for
if(u==-1)
return -1;
vis[u]=true;
ans+=d[u];
for int v=1 to v<=n
{
if(vis[v]==false&&G[u][v]!=inf&&G[u][v]<d[v])
d[v]=G[u][v];
}
end for
}
return ans;
}
int main()
{
定义u,v,c;
输入 n m;
fill(G[0],G[0]+N*N,inf);
for int i=1 to i<=m
{
输入u v c;
G[u][v]=G[v][u]=c;
}
int ans=prim();
if(ans==-1)
cout<<"-1";
else
cout<<ans;
end if
return 0;
}
2.3.2代码截图
2.3.3本题PTA提交列表说明
- Q1:邻接矩阵的初始化不对
- A1:模仿书上的prim算法,将min置为inf
3、上机考试错题及处理办法(-2--2分)
3.1.截图错题代码
3.2 错的原因及处理方法
- Q1:这是上机考最基本的一题,在考试的时候一直出现段错误,百思不得其解,然后就一直提交,一直段错误。。。头铁只想先把这题写出来,然后上机考就die...
- A1:后来和之前在pta上写的代码仔细对比发现在创建邻接矩阵的时候,for循环从i=0 to i<g.n,但是此时g.n还没有置为n,所以一直段错误。但是devc上确能运行,当时考试的时候就更发现不了哪里错了。