博客作业06--图

1.学习总结(2分)

1.1图的思维导图





1.2 图结构学习体会

深度遍历的思想:

              ①访问顶点v;

      ②依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
      ③若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。

广度遍历的思想:

               ① 访问顶点vi ;
                  ② 访问vi 的所有未被访问的邻接点w1 ,w2 , …wk ;
                  ③ 依次从这些邻接点(在步骤②中访问的顶点)出发,访问它们的所有未被访问的邻接点; 依此类推,直到图中所有访问过的顶点的邻接点都被访问;

深度优先

数组表示:查找所有顶点的所有邻接点所需时间为O(n2),n为顶点数,算法时间复杂度为O(n2)   

广度优先

数组表示:查找每个顶点的邻接点所需时间为O(n2),n为顶点数,算法的时间复杂度为O(n2)

Kruskal VS Prim

方法上:Kruskal在所有边中不断寻找最小的边,Prim在U和V两个集合之间寻找权值最小的连接,共同点是构造过程都不能形成环。
时间上:Prim适合稠密图,复杂度为O(n * n),因此通常使用邻接矩阵储存,复杂度为O(e * loge),而Kruskal多用邻接表,稠密图 Prim > Kruskal,稀疏图 Kruskal > Prim。
空间上: Prim适合点少边多,Kruskal适合边多点少。

Dijkstra算法

算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。

拓扑排序算法

执行步骤,由AOV网构造拓扑序列的拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止。
(1) 选择一个入度为0的顶点并输出之;
(2) 从网中删除此顶点及所有出边。
循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,否则输出的顶点序列就是一种拓扑序列

2.PTA实验作业(4分)

2.1 题目1 7-4 公路村村通(30 分)

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

定义数组G存放两条路的预算成本 
  初始化数组G;
  for i=1  to N
    输入两条道路编号及预算成本
	 给G赋初值
   定义数组lowcost,closest分别用来标记最近顶点已访问过和最少金额
   for i=0  to N
      在(V-U)中找出离U最近的顶点k,k记录最近顶点的编号 
      遍历数组G 
         如果顶点未被访问过且顶点K到顶点的最少金额小于该顶点的预算成本,则将
		 lowcost[j]=G[k][j];closest[j]=k;
	
  遍历结束将数组中的最少金额相加
end 

2.3 代码截图



2.4 PTA提交列表说明。

本题其主要思路就是求最小生成树的问题,采用prim算法,一开始按照书上的prim算法写的,没有考虑到其边界条件,然后提交果然是边界测试点过不了

后来加了


但是还是有两个测试点过不了,后来是最后的金额也需判断


2.1 题目:7-7 旅游规划(25 分)

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

定义数组ways[505][505][2];用于储存路径的长度,费用  
dist[505],cost[505];分别储存由st出发点到个点的最短路径及其费用  
visited[505] = {0};储存个点是否加入集合中
初始化数组ways,dist,cost
  for i=0  to M  循环找到最短路径或最少金额 
     for  j=0  to  M 
        找到与初始顶点最近的顶点,用mindis保存该顶点
	 visited标记该顶点已被访问过
	for  j=0   to  M
	    如果顶点未被访问过,且到起始顶点的路径大于最短路径
		  则将最短路径附给dist[j];同时金额也相应改变
		如果距离相等则只改变金额
end  

2.3 代码截图



2.4 PTA提交列表说明。

旅游规划这题其主要思路也即最短路径的问题,采用Dijkstra算法,这题没有考虑到其城市是可以从0开始的,还有当最短路径有多条时,需考虑最便宜的路径导致提交时答案错误,

2.1 题目:7-2 排座位(25 分)

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

定义数组aor存放两个人的关系
   while M--
     输入两位宾客以及两人的关系数
	 用数组aor记录两位宾客的关系
	 if  宾客关系数为1
	    则将这两位宾客的编号放入并查集
	while K--
	  输入要查阅的宾客编号m,n 
	    如果aor[m][n]=1,则输出No problem
		如果aor[m][n]=-1,
		   如果在并查集中找到m,n,则输出OK but...
		   否则输出No way
		否则
		    如果在并查集中找到m,n,则输出No problem
			否则输出OK
end 

2.3 代码截图



2.4 PTA提交列表说明。


这题一开始是打算用Floyd算法做的,但总是答案错误,后来改用了上一章学习的并查集做的,其解题思路与微信朋友圈的类似,改用并查集后简单多了,但是在写的时候最大值考虑错误

3.截图本周题目集的PTA最后排名(3分)

3.1 PTA排名(截图带自己名字的排名)

3.2 我的总分:195

4. 阅读代码(必做,1分)

代码:7-8 城市间紧急救援(25 分)

思路: 基于dijkstra算法的问题。 要考虑最优路径上的点权和尽可能大,所以出现两路径长度相等时要进行关于点权和的判断。另外还要记录最短路径的条数,只需开一个数组记载,每次更新时基于上一点的最短路径条数更新即可。每次更新最优路径时,将上一点记录在theway数组,用于最后输出最优路径。
代码

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int N,M,S,D;
int graph[505][505],dis[505],p[505],sum[505],ans[505],theway[505];
//  邻接矩阵 。最短距离 ,每个点的消防队数目, 最多消防队数目, 最短路径条数,经过此点的最优路径的上一个点
bool vis[505];  //记录是否访问此点
void dijkstra()
{
    ans[S] = 1;
    vis[S] = true;
    sum[S] = p[S];
    int min_poi;

    while(1)
    {
        min_poi = N;
        for(int i = 0 ; i < N; ++i)
        {
            if( !vis[i] && dis[i] < dis[min_poi])
            {
                min_poi = i;
            }
        }
        if(min_poi == N) break;
        vis[min_poi] = true;
        for(int i = 0; i < N; ++i)
        {
            if(!vis[i])
            {
                if(dis[i] > dis[min_poi] + graph[min_poi][i])
                {
                    dis[i] = dis[min_poi] + graph[min_poi][i];
                    ans[i] = ans[min_poi];
                    sum[i] = sum[min_poi] + p[i];
                    theway[i] = min_poi;
                }
                else if(dis[i]==dis[min_poi] + graph[min_poi][i])
                {
                    ans[i] += ans[min_poi];
                    if( sum[i] < sum[min_poi] + p[i])
                        {
                            sum[i] = sum[min_poi] +p[i];
                            theway[i] = min_poi;
                        }
                }
            }
        }
    }
}
int main()
{
    int a,b,c;
    scanf("%d%d%d%d",&N,&M,&S,&D);
    for(int i = 0; i < N; ++i)
        for(int j = 0; j < N; ++j)
         graph[i][j] = inf;
    for(int i = 0; i < N; ++i )
    {
        vis[i] = false;
        scanf("%d",&p[i]);
    }
    for(int i = 0; i < M; ++i)
    {
        scanf("%d%d%d",&a,&b,&c);
        graph[a][b] = graph[b][a] = c;
    }
    for(int i = 0; i < N; ++i)
        {
            dis[i] = graph[S][i];
            if(dis[i] != inf) theway[i] = S;
            if(S != i && graph[S][i] != inf)
            {
                sum[i] = p[i] + p[S];
                ans[i] = 1;
            }
        }
    dis[N] = inf;
    dijkstra();
    printf("%d %d\n", ans[D], sum[D]);
    int answay[505],rear = 0;
    int thepoi = D;
    while(1)                         //   把所求路径上的点储存到数组中,再倒序输出
    {
        answay[rear++] = theway[thepoi];
        thepoi = theway[thepoi];
        if(thepoi == S) break;
    }
    for(int i = (rear - 1); i >= 0; --i)
        printf("%d ",answay[i]);
    printf("%d",D);
    return 0;
}
posted @ 2018-06-17 19:10  千辰烊烊  阅读(163)  评论(0编辑  收藏  举报