另外开一个need数组记录一下需要的花费就好了,更新最短路的时候要分开:一种是更新最短路和花费,另一种是只更新花费。
#pragma warning(disable:4996)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 10005;
const int M = N * 4;
int fst[N], nxt[M], to[M], dist[M], cost[M], e;
int n, m;
bool in[N];
int dis[N];//最短路长度
int need[N];//表示在已有的路径下还需要花费need[i]就能使得i最短路不变
void add(int u, int v, int c, int d) {
to[e] = v;
cost[e] = c;
dist[e] = d;
nxt[e] = fst[u];
fst[u] = e++;
}
int prim() {
memset(in, false, sizeof in);
memset(dis, 0x3f, sizeof dis);
memset(need, 0x3f, sizeof need);
queue<int>q;
q.push(1);
in[1] = true;
dis[1] = 0;
need[1] = 0;
while (!q.empty()) {
int u = q.front(); q.pop();
in[u] = false;
for (int i = fst[u]; ~i; i = nxt[i]) {
int v = to[i], c = cost[i], d = dist[i];
if (dis[v] > dis[u] + d) {//更新最短路和花费
dis[v] = dis[u] + d;
need[v] = c;
if (!in[v]) {
q.push(v);
in[v]=true;
}
}
else if (dis[v] == dis[u] + d&&need[v] > c) {//更新最小花费
need[v] = c;
if (!in[v]) {
q.push(v);
in[v] = true;
}
}
}
}
int ret = 0;
for (int i = 1; i <= n; i++) ret += need[i];
return ret;
}
int main() {
//freopen("in.txt", "r", stdin);
while (scanf("%d %d", &n, &m) && n) {
e = 0;
memset(fst, -1, sizeof fst);
for (int i = 0; i < m; i++) {
int u, v, c, d;
scanf("%d%d%d%d", &u, &v, &d, &c);
add(u, v, c, d);
add(v, u, c, d);
}
printf("%d\n", prim());
}
return 0;
}