Question 250.2022 Winter Holiday Ladder Competition Training-7-15 Inter-city Emergency Rescue (25 points)


Question 250.2022 Winter Holiday Ladder Competition Training-7-15 Inter-city Emergency Rescue (25 points)


1. The topic

insert image description here
insert image description here

2. Problem solving

/*
//错误代码
#include <bits/stdc++.h>

using namespace std;

const int Inf=0x3f3f3f3f;
const int maxn=550;

int N,M;
int G[maxn][maxn];
int team[maxn];
int dist[maxn],teamdist[maxn],pathnum[maxn];//pathnum[i]表示到达i点拥有的最短路条数,记住要你求的是最短路径条数,不是那个最短路径拥有的边数!!!
int collected[maxn];
int parent[maxn];

int findMindist()
{
    int minv,v;
    int mindist=Inf;
    for(v=0;v<N;v++)
    {
        if(collected[v]!=1&&dist[v]<mindist)
        {
            mindist=dist[v];
            minv=v;
        }
    }
    if(mindist<Inf)
    {
        return minv;
    }
    else
    {
        return -1;
    }
}

void dijkstra(int s)
{
    int v,w;
    for(v=0;v<N;v++)
    {
        dist[v]=G[s][v];
        teamdist[v]=team[v];
        if(dist[v]<Inf)
        {
            parent[v]=s;
            pathnum[v]=1;
        }
    }
    collected[s]=1;
    dist[s]=0;
    while(1)
    {
        v=findMindist();
        if(v==-1)
        {
            break;
        }
        collected[v]=1;
        for(w=0;w<N;w++)
        {
            if(collected[w]!=1&&G[v][w]<Inf)
            {
                if(G[v][w]+dist[v]<dist[w])
                {
                    dist[w]=G[v][w]+dist[v];
                    teamdist[w]=team[v]+teamdist[v];
                    parent[w]=v;
                    pathnum[w]=pathnum[v];//通向w的路数继承v
                    //cout<<pathnum[v]<<endl;
                }
                else if(G[v][w]+dist[v]==dist[w])
                {
                    pathnum[w]+=pathnum[v];//只要有路权松弛出相同权的,通向w的路数多加上v的!!!
                    if(team[v]+teamdist[v]>teamdist[w])
                    {
                        teamdist[w]=team[v]+teamdist[v];
                        parent[w]=v;
                    }
                    //cout<<pathnum[w]<<endl;
                }
            }
        }
    }
}

int main()
{
    fill(G[0],G[0]+maxn*maxn,Inf);
    fill(parent,parent+maxn,-1);
    fill(collected,collected+maxn,0);
    int S,D;
    cin>>N>>M>>S>>D;
    for(int i=0;i<N;i++)
    {
        scanf("%d",&team[i]);
    }
    for(int i=0;i<M;i++)
    {
        int v1,v2,weight;
        scanf("%d%d%d",&v1,&v2,&weight);
        G[v1][v2]=weight;
        G[v2][v1]=weight;
    }
    dijkstra(S);
    int v=D;
    stack<int> s;
    s.push(v);
    while(parent[v]!=-1)
    {
        v=parent[v];
        s.push(v);
    }
    printf("%d %d\n",pathnum[D],teamdist[D]);//路数是等于点数-1啊!!!不知道你当时在想啥,输出一个点数出去的
    while(!s.empty())
    {
        printf("%d",s.top());
        s.pop();
        if(!s.empty())
        {
            putchar(' ');
        }
    }
}
*/
#include <bits/stdc++.h>

using namespace std;

const int Inf = 0x3f3f3f3f;
const int maxn = 550;

int N, M;
int G[maxn][maxn];
int team[maxn];
int dist[maxn], teamdist[maxn], pathnum[maxn]; //要你求的是最短路径条数,不是那个最短路径拥有的边数!!!
int collected[maxn];
int parent[maxn];

int findMindist()
{
    
    
    int minv, v;
    int mindist = Inf;
    for (v = 0; v < N; v++)
    {
    
    
        if (collected[v] != 1 && dist[v] < mindist)
        {
    
    
            mindist = dist[v];
            minv = v;
        }
    }
    if (mindist < Inf)
    {
    
    
        return minv;
    }
    else
    {
    
    
        return -1;
    }
}

void dijkstra(int s)
{
    
    
    int v, w;
    for (v = 0; v < N; v++)
    {
    
    
        dist[v] = G[s][v];
        // teamdist[v] = team[v];
        if (dist[v] < Inf)
        {
    
    
            parent[v] = s;
            pathnum[v] = 1;
        }
    }
    // collected[s] = 1; //这里的问题,导致第一个点的队伍数据不更新(teamdist[w] = team[w] + teamdist[0],需要teamdist[0]的数据)!!!
    fill(teamdist,teamdist+maxn,0);
    dist[s] = 0;
    teamdist[s]=team[s];
    while (1)
    {
    
    
        v = findMindist();
        if (v == -1)
        {
    
    
            break;
        }
        collected[v] = 1;
        for (w = 0; w < N; w++)
        {
    
    
            if (collected[w] != 1 && G[v][w] < Inf)
            {
    
    
                if (G[v][w] + dist[v] < dist[w])
                {
    
    
                    dist[w] = G[v][w] + dist[v];
                    teamdist[w] = team[w] + teamdist[v];//应该是加最后一个结点!!!
                    parent[w] = v;
                    pathnum[w] = pathnum[v]; //通向w的路数继承v
                    // cout<<pathnum[v]<<endl;
                }
                else if (G[v][w] + dist[v] == dist[w])
                {
    
    
                    pathnum[w] += pathnum[v]; //只要有路权松弛出相同权的,通向w的路数多加上v的
                    if (team[w] + teamdist[v] > teamdist[w])
                    {
    
    
                        teamdist[w] = team[w] + teamdist[v]; //应该是加最后一个结点!!!
                        parent[w] = v;
                    }
                    // cout<<pathnum[w]<<endl;
                }
            }
        }
    }
}

int main()
{
    
    
    fill(G[0], G[0] + maxn * maxn, Inf);
    fill(parent, parent + maxn, -1);
    fill(collected, collected + maxn, 0);
    int S, D;
    cin >> N >> M >> S >> D;
    for (int i = 0; i < N; i++)
    {
    
    
        scanf("%d", &team[i]);
    }
    for (int i = 0; i < M; i++)
    {
    
    
        int v1, v2, weight;
        scanf("%d%d%d", &v1, &v2, &weight);
        G[v1][v2] = weight;
        G[v2][v1] = weight;
    }
    dijkstra(S);
    int v = D;
    stack<int> s;
    s.push(v);
    while (parent[v] != -1)
    {
    
    
        v = parent[v];
        s.push(v);
    }
    printf("%d %d\n", pathnum[D], teamdist[D]); //路数是等于点数-1啊!!!不知道你当时在想啥,输出一个点数出去的
    while (!s.empty())
    {
    
    
        printf("%d", s.top());
        s.pop();
        if (!s.empty())
        {
    
    
            putchar(' ');
        }
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324345644&siteId=291194637