Think:
1知识点:最短路-spfa算法
2题意:n个城市m条路,每条路的信息包括起点(u)、终点(v)、长度(d)、花费(c),询问在保证1号城市到其它城市距离最短的条件下,连通n个城市的最少花费。
2.1数据范围:
1 <= n <= 1e4
0 <= m <= 2e4
1 <= d <= 1000
1 <= c <= 1000
3错误反思:
3.1:spfa算法求最短路中,手动模拟队列时注意如果不是用循环队列需要注意队列的大小(因为虽然在某一时刻队列中不会出现重复的元素,但某一元素可能会多次入队更新最短路)
以下为Accepted代码——循环队列
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 10414;
const int M = 40414;
struct Edge{
int u, v, d, c;
int next;
}edge[M];
int cnt, head[N];
int vis[N], dis[N], cost[N];
int op, tp, link[N];
void add_edge(int u, int v, int d, int c);
void spfa(int n);
int main(){
int n, m, i, u, v, d, c;
while(~scanf("%d %d", &n, &m) && (n || m)){
cnt = 0;
memset(head, -1, sizeof(head));
for(i = 0; i < m; i++){
scanf("%d %d %d %d", &u, &v, &d, &c);
add_edge(u, v, d, c);
add_edge(v, u, d, c);
}
spfa(n);
}
return 0;
}
void add_edge(int u, int v, int d, int c){
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt].d = d;
edge[cnt].c = c;
edge[cnt].next = head[u];
head[u] = cnt++;
return;
}
void spfa(int n){
int i, u, v, d, c, sum;
memset(vis, 0, sizeof(vis));
memset(dis, inf, sizeof(dis));
memset(cost, inf, sizeof(cost));
op = tp = 0;
vis[1] = 1, dis[1] = 0, cost[1] = 0;
link[tp++] = 1;
while(true){
op %= N;
tp %= N;
if(op == tp) break;
u = link[op++];
vis[u] = 0;
for(i = head[u]; ~i; i = edge[i].next){
v = edge[i].v, d = edge[i].d, c = edge[i].c;
if(dis[v] > dis[u] + d || (dis[v] == dis[u] + d && cost[v] > c)){
dis[v] = dis[u] + d;
cost[v] = c;
if(!vis[v]){
vis[v] = 1;
link[tp++] = v;
}
}
}
}
sum = 0;
for(i = 1; i <= n; i++){
sum += cost[i];
}
printf("%d\n", sum);
return;
}