题目十三

题目:Emergency

我的代码:

//ng了70%,求最短路径条数的方法参照了参考代码的,但是也没能通过
#include<iostream>
#include<vector>
using namespace std;

int const MaxVertex = 500;
#define Vertex int
#define EdgeWeight int
#define Infinity 65535

//边的定义
typedef struct{
    Vertex vf;
    Vertex vt;
    EdgeWeight weight;
}Edge;

//图的定义
typedef struct{
    int vn; //节点数
    int en; //边数
    EdgeWeight GraphMatrix[MaxVertex][MaxVertex]; //图矩阵---这里的MaxVertea需要为常量
    int rescue[MaxVertex];  //救援队矩阵
}Graph;

//先初始化图
Graph* CreatGraph(Graph *G){
    for(int i = 0;i < MaxVertex;i++){
        G->rescue[i]=0;
        for(int j = 0;j < MaxVertex;j++){
            G->GraphMatrix[i][j] = Infinity;
        }
    }
    return G;
}

//根据输入构建图
Graph* BuildGraph(Graph *G,Vertex &V1,Vertex &V2){
    cin>>G->vn>>G->en>>V1>>V2;
    Edge *E;
    E = new Edge;
    for(int i = 0;i < G->vn;i++)
        cin>>G->rescue[i];
    for(int i = 0;i < G->en;i++){
        cin>>E->vf>>E->vt>>E->weight;
        G->GraphMatrix[E->vf][E->vt] = E->weight;  //注意是无向图
        G->GraphMatrix[E->vt][E->vf] = E->weight;
    }
    return G;
}

//返回目前为止路径累积最短的节点
Vertex MinPathV(Graph *G,int Dist[],int Collect[]){
    int Min = Infinity;
    int pos;
    for(int i = 0;i < G->vn;i++){
        if(Collect[i] == false && Dist[i] < Min) { //在未扫描过的顶点中选择
            pos = i;
            Min = Dist[i]; //只有还有没有访问过的节点时候,Min才会更新
        }
    }
    if(Min < Infinity) return pos;
    else return -1;
}

//迪杰斯特拉算法
//**collected[]是判断哪些节点已经被访问的矩阵、path[v]是存储v节点的上一个节点的矩阵
//**dist[v]是存储到v的路径代价,Res[]是存储到v的路径的救援队数量**//
void Djs(Graph *G,Vertex v1,int Collect[],int Path[],int Dist[],int Res[],vector<int>count){
    for(int i = 0;i < G->vn;i++){
        Dist[i] = G->GraphMatrix[v1][i];
        Path[i] = v1;
        Res[i] =  G->rescue[v1] + G->rescue[i];
        Collect[i] = false;
    }
    Collect[v1] = true;Dist[v1] = 0;
    
    Vertex v;
    while(true){
        v = MinPathV(G,Dist,Collect);
        if(v == -1) break;  //当v中找不到没有访问过的节点,则退出while循环
        Collect[v] = true; //注意放到已访问集合中是在判断为最小值之后
        for(int i = 0;i < G->vn;i++){
            if(Collect[i] == false && Dist[i] > Dist[v] + G->GraphMatrix[v][i]){
                Dist[i] = Dist[v] + G->GraphMatrix[v][i];
                Path[i] = v;
                Res[i] =  Res[v] + G->rescue[i];
                count[i] = count[v];  //直接赋值
            }
            else if(Collect[i] == false && Dist[i] == Dist[v] + G->GraphMatrix[v][i]){
                count[i] += count[v];  //原来的加上新增的
                if(Res[i] < Res[v] + G->rescue[i]){
                    Path[i] = v;
                    Res[i] =  Res[v] + G->rescue[i];
                }
            }
        }
    }
}

//按要求寻找最短路径
void FindThePath(Graph *G,Vertex &s,Vertex &d){
    Vertex Collect[G->vn];
    Vertex Path[G->vn];
    Vertex Dist[G->vn];
    Vertex Res[G->vn];
    vector<int>count(G->vn,1);
    
    Djs(G,s,Collect,Path,Dist,Res,count);
    
    cout<<count[d]<<' '<<Res[d];
}

int main(){
    Graph *G;
    G = new Graph;
    Vertex S,D;
    G = CreatGraph(G);
    G = BuildGraph(G,S,D);
    FindThePath(G,S,D);
}

评注:

第二次做图的题目,遇到很多问题

(1)宏定义的时候再句末不需要加逗号

(2)定义数据的时候数据大小不能是一个变量名,如果要填变量名,要定义成const常量

(3)在用引用作为函数形参,然后把图结构体传进去的时候,编译器直接死机,后面改成用指针,不会有这个问题

(4)定义指针后记得要初始化指针

 

参考代码:

链接:https://www.nowcoder.com/questionTerminal/8d3c64413a74486f87de8ab1285fe04f
来源:牛客网

//PAT和牛客都AC了,有疑问可以评论
#include<iostream>
#include<algorithm>
#define inf 65535
using namespace std;
int n,m,s,t,used[500]={0},cost[500][500],mincost[500],path[500],amount[500],maxget[500];
void dijkstra(int s)
{
    int u,v,i,j;
    fill(path,path+500,1);   //这个函数挺强 
    mincost[s]=0;
    while(1)
    {
        v=-1;
        for(u=0;u<n;u++)
            if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u;
        if(v==-1) break;
        used[v]=1;
        for(u=0;u<n;u++)
        {
            if(!used[u]&&mincost[u]>mincost[v]+cost[v][u])
            {
                mincost[u]=mincost[v]+cost[v][u];
                maxget[u]=maxget[v]+amount[u];
                path[u]=path[v];
            }
            else if(!used[u]&&mincost[u]==mincost[v]+cost[v][u])
            {
                path[u]+=path[v];
                maxget[u]=max(maxget[u],maxget[v]+amount[u]);
            }    
        }
    }
}
int main()
{
    int i,j,u,v;
    for(i=0;i<500;i++)
        for(j=0;j<500;j++)
            cost[i][j]=inf;  //初始化图矩阵 
    cin>>n>>m>>s>>t;
    for(i=0;i<n;i++)
    {
        mincost[i]=inf;    //到每个地方的最小长度 
        cin>>amount[i];   //amount为每个地方的营救队数量 
        maxget[i]=amount[i];
    }  
    for(i=0;i<m;i++)
    {
        cin>>u>>v;
        cin>>cost[u][v];
        cost[v][u]=cost[u][v];
    }
    dijkstra(s);
    cout<<path[t]<<' '<<maxget[t];
    return 0;
}

评注:

(1)并没有用结构体来描述图的机构,只是用数据来实现

(2)fill(a,a+n,x)这个给数组初始化的方法要学会使用

(3)max()的方法要学会使用,上面说的两个函数都是在#include<algorithm>头文件里面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值