题意:在一个无向图中,每条边上有建设的花费和路径的长度,要求求得,在保持每个点到1号点最小距离不变的情况下,求最小的总花费;
思路:用dijkstra 找出每个点的最小距离,再重新从1出发,找出每个点对应的最小花费;(一开始自己想的是直接在dijkstra的时候把花费算出来,好想不对)
#include <cstdio> #include <iostream> #include <cstring> #include <string> #include <algorithm> #include <vector> #include <queue> const int maxn = 10007; const int inf =1e9; using namespace std; struct node{ int to,d,c; node(){} node (int to,int d,int c):to(to),d(d),c(c){} }; vector<node>mp[maxn]; int dis[maxn],cost[maxn],n,m,ans = 0; void init(){ for(int i=1;i<=n;i++) { mp[i].clear(); dis[i] = inf; cost[i] = 0; } } void add(int u,int v,int d,int c) { mp[u].push_back(node(v,d,c)); } int main(){ while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0)break; init(); for(int i=1;i<=m;i++) { int u,v,d,c; scanf("%d%d%d%d",&u,&v,&d,&c); add(u,v,d,c); add(v,u,d,c); } priority_queue<pair<int,int> >q; dis[1]=0; cost[1]=0; q.push (make_pair(-dis[1],1)) ; while(!q.empty()) { int now = q.top().second; q.pop(); for(int i=0;i<mp[now].size();i++) { int v=mp[now][i].to; int d=mp[now][i].d; int c=mp[now][i].c; if(dis[v]>dis[now]+d) { dis[v] = dis[now]+d; q.push (make_pair(-dis[v],v)); } } } ans = 0; for(int i=2;i<=n;i++) //计算最小花费 { int minc = inf; for(int j=0;j<mp[i].size();j++) //只用算和已修好的点中最小的花费 { node tmp = mp[i][j]; if(tmp.d+dis[tmp.to]==dis[i]&&minc>tmp.c) { minc = mp[i][j].c; } } ans += minc; } printf("%d\n",ans); } return 0; }