数据结构:图
1.学习总结
(1)掌握图的相关概念,包括图、有向图、无向图、完全图、子图、连通图、度、入度、出度、简单回路和环等定义。
(2)重点掌握图的各种存储结构,包括邻接矩阵和邻接表等。
(3)重点掌握图的基本运算,包括创建图、输出图、深度优先遍历、广度优先遍历等。
(4)掌握图的其他运算,包括最小生成树、最短路径、拓扑排序和关键路径等的算法。
(5)灵活运用图这种数据结构解决一些综合应用问题。
1.1图的思维导图
1.2图结构学习体会
- 深度遍历算法:一条路走到底,没路时再返回上一个找其他路,循环操作到遍历完所有顶点为止。
- 广度遍历算法:先输出与首个顶点有路的所有顶点,再按先进先出法则输出与该顶点有路的顶点。
- Prim和Kruscal算法:均为求最小生成树的算法,前者时间复杂度为O(n^2),后者为O(elog2(e))。
- Dijkstra算法:以邻接矩阵作为存储结构,其算法时间复杂度为O(n^2)。
- 拓扑排序算法:有向图,用邻接表定义,从入度为0的点出发走到没有前驱的顶点。
2.PTA实验作业
2.1.1题目1:图着色问题
2.1.2设计思路
直接用图的遍历,遍历的时候判断是否颜色相等即可。任选一顶点着色1,在图中尽可能多的用颜色1着色,当不能用颜色1着色时,转用其他颜色,直到所有顶点都被着色为止。(PS:伪代码思路为最初思路,实际代码已经修改成更精简的方法)
伪代码:
while each vertex in G 初始化颜色为0
vertex[0]=1//选初始点颜色置为1
置颜色种类color=0;
循环置所有顶点着色
color++;//取下一颜色
while each vertex in G
if vertex[i]已着色,转下一顶点
else
若该点用color着色与其他邻接点颜色不冲突
vertex[i]=color;
否则不着色
2.1.3代码截图
2.1.4PTA提交列表说明
开始的多次编译错误是因为代码使用的是C++,而PTA的初始编译器是C(gcc),经发现并改正后得以解决。答案错误是因为没有按照格式输出,部分正确是因为对题目的多种情况考虑不全,几经修改,最后答案正确。
2.2.1题目2:排座位
2.2.2设计思路
假设俩人A和B,需考虑如下情况:
(1) 如果A、B是直接的朋友,输出 No problem
(2)否则如果A、B不敌对,输出OK
(3)否则如果A、B敌对但他们有共同的朋友,输出OK but...
(4)否则A、B敌对并且没有共同的朋友,输出No way
2.2.3代码截图
2.2.4PTA提交列表说明
开始的编译问题依然是编译器的选择问题,随后的答案错误是因为输出格式没有严格按照要求,紧接着的多次部分正确是因为题目的多种情况没整理完全,经一步步的完善后答案正确。
2.3.1题目3:六度空间
2.3.2设计思路
该题主要是解决超时的问题卡的比较久。
比如像visited[],不是简单的0.1定义,不然每对一个数字进行遍历都还要重置visited[]。
2.3.3代码截图
2.3.4PTA提交列表说明
编译错误依旧是编译器的选择问题,多次答案错误是因为没有深入理解题意,以致于错漏百出,几番周折后答案正确。
3.本周PTA题目集最后排名截图
本次题目集总分:135分(时间:2018/6/17 13:12)
3.1PTA排名
47
3.2我的总分
135
4.阅读代码
天梯地图代码阅读:
最短路,麻烦的是多条最短路中推荐最优的路线,并输出路径。路径的还原可以不断记录前驱节点,注意的是每个节点的前驱节点可能不止一个,全需要记录,最后搜索最优路径。
- #include <iostream>
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <string>
- #include <algorithm>
- #include <cmath>
- #include <map>
- #include <queue>
- #include <stack>
- #include <set>
- using namespace std;
- const int INF = 0x3f3f3f3f;
- const int maxn = 1e4+10;
- /*----------------------------------------------------------------head------------------------------------------------------------------*/
- int n,m,ss,dd;
- int T[510][510],D[510][510],dist[510],disd[510],vist[510],visd[510],pret[510]/*记录最小时间的前驱*/,pred[510]/*记录最短距离的前驱*/,SUM[510]/*记录节点个数*/;
- int u,v,is,d,t;
- void print(int cnt,int c[]){//打印路径
- for(int i = cnt-1; i >= 0; i--){
- if(i != cnt-1)
- printf(" =>");
- printf(" %d",c[i]);
- }
- puts("");
- }
- /*------------------------------------------------------------dijkstra-----------------------------------------------------------------*/
- //求解最小时间的最短路
- void dijkstraT(){
- for(int i = 0; i < n; i++){//初始化
- dist[i] = T[ss][i];
- disd[i] = D[ss][i];
- vist[i] = visd[i] = 0;
- pret[i] = pred[i] = ss;
- }
- dist[ss] = disd[ss] = 0;//初始化
- vist[ss] = visd[ss] = 1;//初始化
- pret[ss] = -1;//初始化
- int Min,pos;
- for(int i = 1; i < n; i++){
- Min = INF;
- for(int j = 0; j < n; j++){
- if(!vist[j] && dist[j]<Min){
- Min = dist[j];
- pos = j;
- }
- }
- vist[pos] = 1;
- for(int j = 0; j < n; j++){
- if(!vist[j] && dist[j]>dist[pos]+T[pos][j]){
- dist[j] = dist[pos]+T[pos][j];
- disd[j] = disd[pos]+D[pos][j];
- pret[j] = pos;
- }
- else if(!vist[j] && dist[j] == dist[pos]+T[pos][j]){
- if(disd[j] > disd[pos]+D[pos][j]){//时间相同选距离最短
- disd[j] = disd[pos]+D[pos][j];
- pret[j] = pos;
- }
- }
- }
- }
- }
- //求解最短距离的最短路
- void dijkstraD(){
- for(int i = 0; i < n; i++){//初始化
- disd[i] = D[ss][i];
- visd[i] = 0;
- pred[i] = ss;
- SUM[i] = 1;
- }
- disd[ss] = 0;//初始化
- visd[ss] = 1;//初始化
- pred[ss] = -1;//初始化
- int Min,pos;
- for(int i = 1; i < n; i++){
- Min = INF;
- for(int j = 0; j < n; j++){
- if(!visd[j] && disd[j]<Min){
- Min = disd[j];
- pos = j;
- }
- }
- visd[pos] = 1;
- for(int j = 0; j < n; j++){
- if(!visd[j] && disd[j]>disd[pos]+D[pos][j]){
- disd[j] = disd[pos]+D[pos][j];
- pred[j] = pos;
- SUM[j] = SUM[pos]+1;
- }
- else if(!visd[j] && disd[j]==disd[pos]+D[pos][j]){//距离相同选节点数最小
- if(SUM[j] > SUM[pos]+1){
- SUM[j] = SUM[pos]+1;
- pred[j] = pos;
- }
- }
- }
- }
- }
- /*------------------------------------------------------------main--------------------------------------------------------------------*/
- int main(){
- scanf("%d %d",&n,&m);
- memset(T,INF,sizeof(T));
- memset(D,INF,sizeof(D));
- while(m--){
- scanf("%d %d %d %d %d",&u,&v,&is,&d,&t);
- if(is){
- if(T[u][v]>t)//去重
- T[u][v] = t;
- if(D[u][v]>d)//去重
- D[u][v] = d;
- }
- else{
- if(T[u][v]>t)//去重
- T[u][v] = T[v][u] = t;
- if(D[u][v]>d)//去重
- D[u][v] = D[v][u] = d;
- }
- }
- scanf("%d %d",&ss,&dd);
- dijkstraT();
- dijkstraD();
- int pt = dd;
- int pd = dd;
- int flag = 1;//flag==1表示两条路径相同,不然不同。
- int a[510],b[510],cnta,cntb;
- cnta = cntb = 0;
- while(pt != -1){
- a[cnta++] = pt;
- pt = pret[pt];
- }
- while(pd != -1){
- b[cntb++] = pd;
- pd = pred[pd];
- }
- if(cnta != cntb)//节点数不同路径肯定不同
- flag = 0;
- else{
- for(int i = 0; i < cnta; i++){
- if(a[i] != b[i]){
- flag = 0;
- break;
- }
- }
- }
- if(flag){
- printf("Time = %d; Distance = %d:",dist[dd],disd[dd]);
- print(cnta,a);
- }
- else{
- printf("Time = %d:",dist[dd]);
- print(cnta,a);
- printf("Distance = %d:",disd[dd]);
- print(cntb,b);
- }
- return 0;
- }