Article directory
Question 250.2022 Winter Holiday Ladder Competition Training-7-15 Inter-city Emergency Rescue (25 points)
1. The topic
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(' ');
}
}
}