PAT甲级1003 Emergency (25分)

PAT甲级1003 Emergency (25分)

题目:在这里插入图片描述
解题思路:由于是第一次接触到图的问题,所以重温了一下数据结构的Dijkstra算法吧,不太会写,在搜集了各种资料之后终于AC,所以做了详细的注释,可能下次遇到Dijkstra会好受一点吧

附上AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxv = 510;//最大顶点数
const int inf  = 1000000000;//无穷大
//n为顶点数,m为边数,st和ed分别为起点和终点
//G为邻接矩阵,weight为点权
//d[]记录最短距离,w[]记录最大点权之和,num[]记录最短路径条数
int n,m,st,ed,G[maxv][maxv],weight[maxv];
int d[maxv],w[maxv],num[maxv];
bool vis[maxv]={
    
    false};//vis[i]==true表示顶点i已访问,初始均为false


void Dijkstra(int s){
    
    //s为起点
    fill(d,d+maxv,inf);//将最短距离填充为inf
    memset(num,0, sizeof(num));//把num数组(最短路径条数)也填满
    memset(w,0, sizeof(w));//把w数组也填满
    d[s]=0;//从s到s的最短距离当然是0啦,因为s是起点鸭,相当于赋初值
    w[s]=weight[s];//w[]记录最大点权之和,weight[s]是起点处的点权,w[s](s的最大点权之和)必然是weight[s]啦
    num[s]=1;//num[s]记录从s到s最短路径条数,显然为1啦
    for(int i=0;i<n;i++){
    
    //循环n次
        int u=-1,MIN=inf;//u使d[u]最小,MIN存放该最小的d[u],u和min是用来记录d[u]的
        for(int j=0;j<n;j++){
    
    
            if(vis[j]== false&&d[j]<MIN){
    
    //找到未访问的顶点中d[]最小的
                u=j;
                MIN=d[u];
            }
        }
        //找不到小于inf的d[u],说明剩下的顶点和起点s不相通
        if(u==-1) return;
        vis[u]=true;//标记u已访问
        for(int v=0;v<n;v++){
    
    
            //如果v未访问,且u能到达v,且以u为中介点可以使d[v]更优
            if(vis[v]==false&&G[u][v]!=inf){
    
    
                if(d[u]+G[u][v]<d[v]){
    
    
                    d[v]=d[u]+G[u][v];//覆盖d[v]
                    w[v]=w[u]+weight[v];//覆盖w[v],加上一个v处的weight值
                    num[v]=num[u];//这个时候最短路径条数就相等啦,num[v]=num[u]
                }else if(d[u]+G[u][v]==d[v]){
    
    //找到一条相同长度的路径
                    if(w[u]+weight[v]>w[v]){
    
    //以u为中介点时候点权更大
                        w[v]=w[u]+weight[v];//w[v]继承w[u]
                    }//注意最短路径条数与点权无关,写在外面
                    num[v]=num[v]+num[u];//到达v的最短路径条数又得加上到达u的最短路径条数,因为从u过来也能到达v了,有两种走法
                }
            }

        }
    }

}
int main(){
    
    
    scanf("%d%d%d%d",&n,&m,&st,&ed);
    for(int i=0;i<n;i++){
    
    
        scanf("%d",&weight[i]);//读入点权
    }
    int u,v;
    fill(G[0],G[0]+maxv*maxv,inf);//初始化图G,因为对于二维数组而言,G[0]才是G[0][0]的首地址
    for(int i=0;i<m;i++){
    
    
        scanf("%d%d",&u,&v);
        scanf("%d",&G[u][v]);//读入边权
        G[v][u]=G[u][v];//从u到u等于从v到u毕竟是无向图
    }

    Dijkstra(st);//DJ上场,从起点进入
    printf("%d %d\n",num[ed],w[ed]);//从终点输出,最短距离条数,最短路径中的最大点权
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43795683/article/details/104256338
今日推荐