题目:给出若干个建筑之间的一些路,每条路都有对应的长度和需要的花费,问在保证源点1到其他个点的距离最短的情况下,最少的花费是多少/
思路:和一般的最短路问题相比,多了一个 数组id【i】,用来记录到达i点在距离最短的情况下是由那条边到达的。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<vector> #include<set> #include<queue> #include<string> #include<algorithm> #define MAXSIZE 1000005 #define LL long long #define INF 0x3f3f3f3f using namespace std; //给出若干个建筑之间的一些路,每条路都有对应的长度和需要的花费, //问在保证源点1 到其他个点的距离最短的情况下,最少的花费是多少 int n,m,vis[MAXSIZE],a[MAXSIZE],k,dist[MAXSIZE],id[MAXSIZE]; struct node { int u; int v; int w; int c; int next; }G[MAXSIZE]; void Add(int u,int v,int w,int c) { G[k].u = u; G[k].v = v; G[k].w = w; G[k].c = c; G[k].next = a[u]; a[u] = k++; } int dij() { memset(vis,0,sizeof(vis)); memset(id,-1,sizeof(id)); dist[1] = 0; int minn ,p; for(int i=1;i<k;i++) { minn = INF; for(int j=1;j<=n;j++) { if(!vis[j] && dist[j] < minn) { minn = dist[j]; p = j; } } if(minn == INF) break; vis[p] = 1; for(int j=a[p];j!=-1;j=G[j].next) { int v = G[j].v; if(dist[v] > dist[p] + G[j].w && !vis[v]) //距离更短就更新 { dist[v] = dist[p] + G[j].w; id[v] = j; } //距离相同,花费更小就更新 else if(id[v]!=-1 && dist[v] == dist[p] + G[j].w && G[j].c < G[id[v]].c && !vis[v]) { id[v] = j; } } } int sum=0; for(int i=1;i<=n;i++) { if(id[i] == -1) continue; else sum += G[id[i]].c; } return sum; } void Init() { memset(a,-1,sizeof(a)); memset(vis,0,sizeof(vis)); for(int i=0;i<MAXSIZE;i++) dist[i] = INF; k = 1; } int main() { int u,v,w,c; while(scanf("%d%d",&n,&m),n+m) { Init(); for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&u,&v,&w,&c); Add(u,v,w,c); Add(v,u,w,c); } int ans = dij(); printf("%d ",ans); } return 0; }