转载请注明该文链接
尝试了一下邻接表
题意:n个点,m条无向边,每条边都有长度d和花费p,给起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
思路:比普通最短路多了一个花费,但是只在距离相同时要求花费最小,所以只需要在松弛条件上做手脚:当距离相等时如果花费更小那么也进行松弛,即将if(d[v]>d[u]+dis)变为if((d[v]>d[u]+dis) || ((d[v]==d[u]+dis) && c[v]>c[u]+cost)),并在松弛操作中加入c[v]=c[u]+cost这项就可以了。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<string> #include<map> #include<queue> #include<algorithm> using namespace std; typedef __int64 ll; const int N=1010; const int M=100010; const ll inf=1LL<<60; struct node { int to; ll dis; ll cost; node *next; }E[M<<1],*G[N],*head; int n,m; ll d[N],c[N]; bool inq[N]; void init() { fill(d,d+N,inf); fill(c,c+N,inf>>2); memset(inq,false,sizeof(inq)); memset(G,0,sizeof(G)); head=E; } inline void add(int a,int b,ll v,ll cost,node *G[]) { head->to=b; head->dis=v; head->cost=cost; head->next=G[a]; G[a]=head++; } void SPFA(int s,ll d[],ll c[],node *G[]) { deque<int> Q; Q.push_back(s); d[s]=0;c[s]=0; while(!Q.empty()) { int u=Q.front();Q.pop_front(); inq[u]=false; for(node *p=G[u];p;p=p->next) { int v=p->to; ll dis=p->dis; ll cost=p->cost; if((d[v]>d[u]+dis) || ((d[v]==d[u]+dis) && c[v]>c[u]+cost)) { d[v]=d[u]+dis; c[v]=c[u]+cost; if(!inq[v]) { inq[v]=true; if(!Q.empty() && d[v]<=d[Q.front()]) Q.push_front(v); else Q.push_back(v); } } } } } int main() { while(scanf("%d%d",&n,&m),n||m) { init(); int a,b; ll dis,cost; for(int i=0;i<m;i++) { scanf("%d%d%I64d%I64d",&a,&b,&dis,&cost); a--,b--; add(a,b,dis,cost,G); add(b,a,dis,cost,G); } int s,t; scanf("%d%d",&s,&t); s--,t--; SPFA(s,d,c,G); printf("%I64d %I64d\n",d[t],c[t]); } return 0; }