算是比较常见的题型,我们要求在最短路的基础上求得最小的花费,因此使用迪杰斯特拉算法。
但是优先队列里面有两种情况,我们先要满足最短路,在最短路相同的情况下,我们对于花费大小进行判断
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=5e5+10; int h[N],ne[N],e[N]; ll w[N],cost[N],idx; ll d[N],st[N],n,m; ll num[N]; ll sum,res; struct node{ ll d,id,c; bool operator <(const node& t) const{ if(d==t.d) return c>t.c; return d>t.d; } }; void add(int a,int b,int c,int d){ e[idx]=b,ne[idx]=h[a],w[idx]=c,cost[idx]=d,h[a]=idx++; } void dij(){ int i; for(i=0;i<=n;i++){ d[i]=1e18; num[i]=1e18; st[i]=0; } priority_queue<node> q; d[0]=0; num[0]=0; q.push({0,0,0}); while(q.size()){ auto t=q.top(); q.pop(); if(st[t.id]) continue; st[t.id]=1; for(i=h[t.id];i!=-1;i=ne[i]){ int j=e[i]; if(d[j]>d[t.id]+w[i]){ d[j]=d[t.id]+w[i]; num[j]=cost[i]; q.push({d[j],j,num[j]}); } else if(d[j]==d[t.id]+w[i]&&num[j]>cost[i]){ num[j]=cost[i]; q.push({d[j],j,num[j]}); } } } sum=0,res=0; for(i=0;i<n;i++){ sum+=d[i]; res+=num[i]; } } int main(){ ios::sync_with_stdio(false); int t; cin>>t; while(t--){ cin>>n>>m; idx=0; for(int i=0;i<=n;i++) h[i]=-1; while(m--){ ll a,b,c,d; cin>>a>>b>>c>>d; add(a,b,c,d); add(b,a,c,d); } dij(); cout<<sum<<" "<<res<<endl; } }