另外开一个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; }