PAT甲级1003

博客围绕求s到d的单源最短路径展开,介绍了Dijkstra算法流程,包括将顶点分为已访问和未访问集合,初始化数组d,遍历顶点更新d值等。题解步骤除必要初始化,还需初始化amount和mind数组,并根据算法最优子结构更新这些数组。

题面略。

思路:其目的是求s(source)到d(destination)的单源最短路径,比较容易想到的是dijikstra算法。

回顾dijisktra算法的流程:将图中所有顶点分为两个集合,一个N,一个U,N表示该集合中的顶点已经访问过,U表示该集合中的顶点还没有访问。

1)初始化:准备一个数组d,d[i]表示从起点到顶点i的最短路径,初始值等于起点与该顶点之间的边的代价cost[s][i],如果并未直接相邻,则令其值为无穷大。

2)遍历顶点:从目前U集合顶点中 d[i] 最小的顶点开始访问,假设这个顶点是 minV,将顶点 minV 加入到N中,再更新顶点 minV 的所有邻居顶点 w 的d[w] = min(d[w], d[minV]+cost[minV][w]).

3)重复步骤2,直到U为空为止。

题解步骤:除了dijisktra的必要初始化之外,由于需要记录最短路径的数目和救援队的数目,先初始化一个amount数组,amount[ i ]表示从s到顶点 i 的最短路径上的最大的救援队伍的数目(值得注意的是,初始化时,amount[s]=team[s], 而其他顶点amount[i] = amount[s]+team[i], 这是因为要到顶点i必然从s出发,所以要加上s中的救援队;不要在准备输出的时候才加上s中的队伍数目,因为有一个检查点是,输入的s和d相同,这样就会出错。);还有一个mind数组,mind[i] 表示从起点s 到顶点i 的最短路径的数目。

根据dijisktra的最优子结构对mind数组,amount数组和d数组进行更新。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;

int t[501];
int amount[501];
int mind[501];
int cost[501][501];
int ds[501];
int ischecked[501];
int n,m,s,d;
const int inf=(1<<30)-1;

void dij(){
    amount[s]=t[s];
    mind[s]=1;
    for(int i=0;i<n;i++){
        ds[i]=cost[s][i];
        ischecked[i]=false;

        if(ds[i]!=inf&&i!=s){
            mind[i]=1;
            amount[i]=t[i]+amount[s];
        }
    }
    ischecked[s]=true;
    for(int node=0;node<n;node++){
        int minV=-1;
        int minC=inf;
        //选最短距离最小的顶点
        for(int i=0;i<n;i++){
            if(!ischecked[i]&&ds[i]<minC){
                minC=ds[i];
                minV=i;
            }
        }
        if(minV==-1){
            continue;
        }
        //访问此顶点
        ischecked[minV]=true;
        for(int i=0;i<n;i++){
            //查看此顶点的所有未访问邻居
            if(!ischecked[i]&&cost[minV][i]<inf){
                //如果两种路径相等,则更新最短路径的数目,更新队伍的数目
                if(ds[i]==ds[minV]+cost[minV][i]){
                    mind[i]+=mind[minV];
                    amount[i]=max(amount[i],amount[minV]+t[i]);
                }
                //如果比原路径小,更新为最短路径,最短路径数目为1.
                else if(ds[i]>ds[minV]+cost[minV][i]){
                    ds[i]=ds[minV]+cost[minV][i];
                    mind[i]=mind[minV];
                    amount[i]=amount[minV]+t[i];
                }
            }
        }
    }
}

int main(void){
    scanf("%d %d %d %d",&n,&m,&s,&d);
    for(int i=0;i<n;i++){
        scanf("%d",&t[i]);
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            cost[i][j]=cost[j][i]=inf;
        }
    }
    for(int i=0;i<m;i++){
        int c1,c2,c;
        scanf("%d %d %d",&c1,&c2,&c);

        if(c<cost[c1][c2]){
            cost[c1][c2]=cost[c2][c1]=c;
        }
    }
    dij();
    printf("%d %d",mind[d],amount[d]);
}


 

### 关于 PAT 甲级 1024 题目 PAT (Programming Ability Test) 是一项编程能力测试,其中甲级考试面向有一定编程基础的学生。对于 PAT 甲级 1024 题目,虽然具体题目描述未直接给出,但从相似类型的题目分析来看,这类题目通常涉及较为复杂的算法设计。 #### 数据结构的选择与实现 针对此类问题,常用的数据结构包括但不限于二叉树节点定义: ```cpp struct Node { int val; Node* lchild, *rchild; }; ``` 此数据结构用于表示二叉树中的节点[^1]。通过这种方式构建的二叉树能够支持多种遍历操作,如前序、中序和后序遍历等。 #### 算法思路 当处理涉及到图论的问题时,深度优先搜索(DFS)是一种常见的解题策略。特别是当需要寻找最优路径或访问尽可能多的节点时,结合贪心算法可以在某些情况下提供有效的解决方案[^2]。 #### 输入输出格式说明 根据以往的经验,在解决 PAT 类型的问题时,输入部分往往遵循特定模式。例如,给定 N 行输入来描述每个节点的信息,每行按照如下格式:“Address Data Next”,这有助于理解如何解析输入并建立相应的数据模型[^4]。 #### 数学运算示例 有时也会遇到基本算术表达式的求值问题,比如分数之间的加减乘除运算。下面是一些简单的例子展示不同情况下的计算结果: - \( \frac{2}{3} + (-2) = -\frac{7}{3}\) -2) = -\frac{4}{3}\) - \( \frac{2}{3} ÷ (-2) = -\frac{1}{3}\) 这些运算是基于样例提供的信息得出的结果[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值