1.1图的思维导图

1,一些概念
顶点 边(无向图) 或 弧(有向图)

完全图,子图,连通图

路径,简单路径(顶点不重复)

生成树(无向图),关键路径,拓扑排序
2,存储结构
2种存储方式,邻接矩阵和邻接表

1)邻接表2)邻接矩阵

3,基本的算法
1)广度优先搜索
队列实现
2)深度优先搜索
栈实现
3)无向图的最小生成树
4)拓扑排序
5)带权有向无环图的关键路径
6)最短路径

1.2 图结构学习体会

对于图这章的内容,不看代码基本都能理解,但是要转换成代码就比较困难。

2.PTA实验作业

下面几题都不是自己写散文,是网上找的答案,有一行一行看过但是还是不能全部了解

 题目1:

7-1 图着色问题

设计思路(伪代码或流程图)

color[n]存储n个顶点的着色方案,可以选择的颜色为1到m

t=1

对当前第t个顶点开始着色:

 若t>n  则已求得一个解,输出着色方案即可

否则,依次对顶点t着色1-m,

   若t与所有其它相邻顶点无颜色冲突,则继续为下一顶点着色;否则,回溯,测试下一颜色。

代码截图

#include<stdio.h>
int visited[501]={0},d[501],k=0;
int a[501][501],v,e,z,x,y,i,j,n;
void dfs(int i)
{
int j;
d[k++]=i;
visited[i]=1;
for(j=1;j<=v;j++)
{
if(a[i][j]==1 && visited[j]==0) dfs(j);
}
}
void dfs1()
{
int i;
for(i=1;i<=v;i++)
{
if(visited[i]==0) dfs(i);
}
}
int main()
{
scanf("%d%d%d",&v,&e,&z);
for(i=0;i<e;i++)
{
scanf("%d%d",&x,&y);
a[x][y]=a[y][x]=1;
}
dfs1();
scanf("%d",&n);
while(n--)
{
int b[501]={0},c[501],e[501],sum=0,flag=1;
for(i=1;i<=v;i++)
{
scanf("%d",&c[i]);
b[c[i]]++;
if(b[c[i]]==1) sum++;
}
if(sum!=z) flag=0;
for(i=0;i<k;i++) e[i]=c[d[i]];
for(i=0;i<k;i++)
{
for(j=0;j<k;j++)
{
if(a[d[i]][d[j]]==1 && e[i]==e[j])
{
flag=0;
break;
}
}
if(flag==0) break;
}
if(flag==0) puts("No");
else puts("Yes");
}
return 0;
}

 PTA提交列表说明。

 

 题目2:

7-2 排座位(25 分)

设计思路(伪代码或流程图)

二维数组判断敌对关系,并查集建立朋友关系

代码截图

#include<iostream>
#include<math.h>
using namespace std;
int a[200];
int map[200][200];
int find(int t)
{
if(t!=a[t])
{
a[t]=find(a[t]);
}
return a[t];
}
int main()
{
int n,m,k,i;
cin>>n>>m>>k;
for(i=1;i<=n;i++)
a[i]=i;
int x,y,z;
for(i=1;i<=m;i++)
{
cin>>x>>y>>z;
map[x][y]=map[y][x]=z;
if(z==1)
{
x=find(x);
y=find(y);
if(x!=y)
a[x]=y;
}
}
int t1,t2;
for(i=1;i<=k;i++)
{
cin>>t1>>t2;
if(map[t1][t2]==1)
{
cout<<"No problem"<<endl;
}
else if(map[t1][t2]==-1)
{
if(find(t1)==find(t2))
cout<<"OK but..."<<endl;
else
cout<<"No way"<<endl;
}
else
{
cout<<"OK"<<endl;
}
}
}

 PTA提交列表说明。

 题目3:

7-4 公路村村通

设计思路(伪代码或流程图)

1、这道题一开始走偏了想直接同floyd算法求出最短路径然后相加了

                     最小生成树能够保证整个拓扑图的所有路径之和最小,但不能保证任意两点之间是最短路径。
                     最短路径是从一点出发,到达目的地的路径最小。

                  2、理清楚了最小生成树与最短路径之间的区别以后就很容易想到用最小生成树算法了,这里选用的是Prim算法

代码截图

#include<stdio.h>
#include<stdlib.h>

#define MAXVEX 1003
#define INFINITY 65535

void CreateGraph( );
int Prim();

int G[MAXVEX][MAXVEX],Nv,Ne;

int main()
{
int f = 0;

scanf("%d %d",&Nv,&Ne);
CreateGraph();
f =Prim();
printf("%d",f);

return 0;
}

void CreateGraph()
{
//用邻接矩阵表示图
int i,j;
int v1,v2,w;

for( i=1; i<=Nv; i++)
{
for( j=1; j<=Nv; j++)
{
G[i][j] = INFINITY; //初始化
}
}

for( i=0; i<Ne; i++) //注意这里是读入边
{
scanf("%d %d %d",&v1,&v2,&w);
G[v1][v2] = w; //读入权值
G[v2][v1]= G[v1][v2]; //无向图对称
}
}


int Prim()
{
int min;
int i,j,k;
int lowcost[MAXVEX];
int cost =0;


lowcost[1] = 0; //初始化第一个权值为0,即v0加入生成树

for( i=2; i<=Nv; i++)
{
lowcost[i] = G[1][i];
}

for( i=2; i<=Nv; i++)
{
min = INFINITY;
j = 1;
k = 0;
while( j<=Nv )
{
if( lowcost[j]!=0 && lowcost[j]<min)
{
min = lowcost[j];
k = j; //将当前最小值的下标存入k
}
j++;
}

if(k==0)
{
return -1; //不连通
}
cost += min;
lowcost[k] = 0; //将当前顶点设置为0,表示此结点已经完成任务

for( j=2; j<=Nv; j++)
{
if( lowcost[j]!=0 && G[k][j]<lowcost[j])
{
//若下标为k顶点各边权值小于此前这些顶点未被加入生成树的权值
lowcost[j] = G[k][j];
}
}

}

return cost;
}

 PTA提交列表说明。

截图本周题目集的PTA最后排名

 阅读代码

#include<stdio.h>
#define MAX_VERTEX 4

typedef char DataType; //图中元素的目标数据类型


typedef struct
{
DataType vertexArr[MAX_VERTEX]; //顶点元素数组

int edgeArr[MAX_VERTEX][MAX_VERTEX]; //边矩阵二维数组

}ArrayGraph;

 

void ArrayGraph_init(ArrayGraph *pGraph);
void ArrayGraph_create(ArrayGraph *pGraph);
void ArrayGraph_DFS(ArrayGraph * pGraph,int n);
static void ArrayGraph_DFS_traverse(ArrayGraph * pGraph,int n,bool*visited);

int main()
{
ArrayGraph g;
ArrayGraph_init(&g); //初始化图
ArrayGraph_create(&g); //创建图
ArrayGraph_DFS(&g,3); //遍历 ,从索引为3的顶点开始
return 0;
}

 

//初始化为一个无圈图 ,也就是边矩阵中,主对角线元素都是0
void ArrayGraph_init(ArrayGraph *pGraph)
{

for (int i = 0; i < MAX_VERTEX; i++)

pGraph->edgeArr[i][i] = 0;

}


void ArrayGraph_create(ArrayGraph *pGraph)
{

for (int i = 0; i < MAX_VERTEX; ++i) //填充顶点数组,也就是输入顶点元素
{
printf("输入第%d个顶点值\n",i+1);

scanf(" %c",&(pGraph->vertexArr[i]));

}

for (int j = 0; j <MAX_VERTEX; ++j) //填充边关系
{
for (int i = j+1; i < MAX_VERTEX; ++i)
{

printf("若元素%c和%c有边,则输入1,否则输入0\t",pGraph->vertexArr[j],pGraph->vertexArr[i]);

scanf("%d",&( pGraph->edgeArr[j][i]));
pGraph->edgeArr[i][j] = pGraph->edgeArr[j][i]; //对称
}
}

}

 

static void ArrayGraph_DFS_traverse(ArrayGraph * pGraph,int n,bool*visited)
{

printf("%c\t",pGraph->vertexArr[n]);

visited[n] = true;

for(int i=0;i<MAX_VERTEX;++i) //以当前已访问的顶点为中心, 在其他所有的顶点中寻找
{
if(pGraph->edgeArr[n][i]!=0 && visited[i]==false) //如果和当前顶点有边,且他们没有被访问过。则访问他们。
{

ArrayGraph_DFS_traverse(pGraph,i,visited);
}
}


for(int i=0;i<MAX_VERTEX;++i) //对图中可能出现的“孤岛”做一次清查
if(visited[i]==false) //如果有孤岛存在,则用同样的方法,遍历他们。
{
ArrayGraph_DFS_traverse(pGraph,i,visited);
}

}

void ArrayGraph_DFS(ArrayGraph * pGraph,int n)
{

bool visited[MAX_VERTEX]; //访问标记数组,
for(int i=0;i<MAX_VERTEX;++i) //局部变量初始化
visited[i] = false;

ArrayGraph_DFS_traverse(pGraph,n,visited);

}

posted on 2018-06-16 11:43  Amberblog  阅读(230)  评论(0编辑  收藏  举报