题解
这题是Dijsktra算法的变形,更新节点的时候需要考虑花费(相当于有两个权值),当路径相同时花费优先选择花费少的,加一个判断即可
#include <cstdio>
#include <vector>
#include <algorithm>
const int maxn=505;
const int INF=100000000;
using namespace std;
struct Edge
{
int to;
int weight;
int cost;
};
vector<Edge> G[maxn];
int speend[maxn], d[maxn],pre[maxn];
int N, M, S, D;
bool vis[maxn] = {false};
void Dijsktra(int tmp);
int main()
{
scanf("%d %d %d %d",&N,&M,&S,&D);
fill(d, d+maxn, INF);
fill(speend, speend+maxn, INF);
fill(pre, pre+maxn, -1);
for(int i=0; i<M; i++)
{
int v1;
Edge e1, e2;
scanf("%d %d %d %d",&v1,&e1.to,&e1.weight,&e1.cost);
e2.to = v1;
e2.cost = e1.cost;
e2.weight = e1.weight;
G[v1].push_back(e1);
G[e1.to].push_back(e2);
}
Dijsktra(S);
int path[maxn], i=1;
path[0]=D;
while(pre[D] != -1)
{
path[i++] = pre[D];
D = pre[D];
}
for(--i; i>=0; i--)
printf("%d ", path[i]);
printf("%d %d", d[path[0]], speend[path[0]]);
return 0;
}
void Dijsktra(int tmp)
{
d[tmp]=0;
speend[tmp]=0;
for(int j=0; j<N; j++)
{
int u=-1, MIN=INF;
for(int i=0; i<N; i++)
{
if (vis[i]==false && d[i]<MIN)
{
u = i;
MIN = d[i];
}
}
if (u == -1)
return;
vis[u] = true;
for (int i=0; i<int(G[u].size()); i++)
{
int v, weight, cost;
v = G[u][i].to;
weight = G[u][i].weight;
cost = G[u][i].cost;
if (vis[v] == false)
{
if (d[u]+weight < d[v])
{
d[v] = d[u]+weight;
pre[v] = u;
speend[v] = speend[u]+cost;
}
else if (d[u]+weight == d[v])
{
if(speend[u]+cost < speend[v])
{
speend[v] = speend[u]+cost;
pre[v] = u;
}
}
}
}
}
}