準備するアレイ:
G [] []グラフは隣接行列として格納され、無限大に初期化され、自己から自己へと0に初期化されます。dist[]は頂点からソースまでの距離を格納し、無限大に初期化されます。pre[]は、パスを出力するために頂点の先行ノードを格納します。 、-1に初期化;
vis []は、頂点がfalseに初期化されたセットSに含まれていることを示すために使用されます。num[]は、0に初期化された最短パスの数を格納するために使用されます。Weight[]は、各ポイントでのレスキューチームの数、つまりポイントの重みを格納します。 、初期化せずに、タイトルで指定されたデータを直接読み込むだけです。
W []は、ソースから頂点までのパスに沿ったレスキューチームの総数を格納するために使用され、0に初期化されます。
この質問の基本的な考え方はDijkstraアルゴリズムですが、この質問は重みのポイントを追加し、最短パスの長さを記録します。したがって、dist []が同じ場合、レスキューチームの数が増えるかどうかを確認する必要があります。増加する場合は、レスキューチームの数W []、プリカーサー配列pre []、および最短パスの数num []を更新します。レスキューチームの数が増えない場合は、最短パスの数も更新することを忘れないでください!(ここでミスをすると、テストポイント1が失敗しました)。
Dijkstraアルゴリズムに入った後、ソースポイントの関連データを初期化する必要があります:dist [S] = 0; pre [S] = -1; num [S] = 1(自分自身への道は1つしかないため、Grandma Chenmoocは教えています); W [S] = Weight [S];注:Sは後で最初のループで処理されるため、vis [S]をtrueに初期化しないでください。
初期化が完了したら、通常のDijkstra操作を開始できます。最初に含まれていない最小のdist []を見つけ、次にそれをセットSに含め、次にそれがSに含まれた後に隣接するサークルに影響するかどうかを確認し、影響する場合はそれに応じて更新します。
この質問のコードは次のとおりです。
#include<stdio.h>
#include<stack>
#define INF 10000000
using namespace std;
#define MAXV 505
int n, G[MAXV][MAXV];
int dist[MAXV];
int pre[MAXV];
bool vis[MAXV] = {false};
int num[MAXV];//路径的数目
int Weight[MAXV];//点权
int W[MAXV];//从原点到某个顶点的城市救援队的数目
void Dijkstra(int S)
{
int i,j,k,z;
int MinDist,MinV;
/*对数据进行必要的基础准备*/
dist[S] = 0;
pre[S] = -1;
num[S] = 1;
W[S] = Weight[S];
/*下面正式进入Dijkstra*/
for(i=0; i<n; i++)
{
MinDist = INF; MinV = -1;
for(j=0; j<n; j++)//找到未被访问过的dist[]
{
if(vis[j]==false&&dist[j]<MinDist)
{
MinDist = dist[j];
MinV = j;
}
}
if(MinV == -1) return;
/*没有退出循环说明找到了,继续执行后面的步骤*/
vis[MinV] = true;
for(k=0; k<n; k++)
{
if(G[MinV][k]<INF&&vis[k]==false)
{
if(dist[MinV]+G[MinV][k] < dist[k])
{
dist[k] = dist[MinV] + G[MinV][k];
pre[k] = MinV;
num[k] = num[MinV];
W[k] = W[MinV] + Weight[k];
}
else if((dist[MinV]+G[MinV][k]==dist[k])&&(W[MinV]+Weight[k]>W[k]))
{
pre[k] = MinV;
num[k] = num[MinV] + num[k];
W[k] = W[MinV] + Weight[k];
}
else if(dist[MinV]+G[MinV][k]==dist[k])
num[k] = num[MinV] + num[k];
}
}
}
}
int main()
{
int N,M,S,D;
int i,j;
scanf("%d %d %d %d",&N,&M,&S,&D);
for(i=0; i<N; i++)
{
scanf("%d",&Weight[i]);
}
int V1,V2,L;
/*初始化*/
n = N;
for(i=0; i<n; i++)
for(j=0; j<n; j++)
{
G[i][j] = INF;
}
/*初始化*/
for(i=0; i<M; i++)
{
scanf("%d %d %d",&V1,&V2,&L);
G[V1][V2] = L;
G[V2][V1] = L;
}
for(i=0; i<n; i++)
{
pre[i] = -1;
num[i] = 0;
dist[i] = INF;
W[i] = 0;
G[i][i] = 0;
}
/*初始化*/
Dijkstra(S);
stack<int> q; int path;
printf("%d %d\n",num[D],W[D]);
while(D!=-1)
{
q.push(D);
D = pre[D];
}
int count = q.size();
for(i=0; i<count-1; i++)
{
path = q.top(); q.pop();
printf("%d ",path);
}
printf("%d",q.top());
return 0;
}