#include<bits/stdc++.h> #define debu using namespace std; const int INF=999999; const int maxn=1e4+50; struct Edge { int from,to,dist; Edge(int a=0,int b=0,int c=0):from(a),to(b),dist(c) {} }; struct HeapNode { int d,u; bool operator < (const HeapNode& rhs) const { return d>rhs.d; } HeapNode(int a,int b):d(a),u(b) {} }; struct Dijkstra { int n,m; int p[maxn]; vector<Edge> edges; vector<int> G[maxn]; bool done[maxn]; void init(int n) { this->n=n; for(int i=0; i<n; i++) G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int dist) { edges.push_back(Edge(from,to,dist)); m=edges.size(); G[from].push_back(m-1); } void dijkstra(int s,int* d,int* p) { priority_queue<HeapNode> q; for(int i=0; i<n; i++) d[i]=INF; d[s]=0; memset(done,0,sizeof(done)); q.push(HeapNode(0,s)); while(!q.empty()) { HeapNode x=q.top(); q.pop(); int u=x.u; if(done[u]) continue; done[u]=true; for(int i=0; i<G[u].size(); i++) { Edge& e=edges[G[u][i]]; if(d[e.to]>d[u]+e.dist) { d[e.to]=d[u]+e.dist; p[e.to]=e.from; q.push(HeapNode(d[e.to],e.to)); } } } } }; int cas=0; int answer; int n,s,t,m,k; Dijkstra ans; int pos1,pos2; int num1,num2; vector<int> step; vector<Edge> fast; int p1[maxn],p2[maxn]; int d1[maxn],d2[maxn]; void solve() { int ans=d1[t]; // cout<<ans<<" ans"<<endl; pos1=-1;pos2=-1; for(int i=0; i<fast.size(); i++) { int x=fast[i].from; int y=fast[i].to; int z=fast[i].dist; // cout<<"flag "<<x<<" "<<y<<" "<<z<<endl; if(ans>d1[x]+z+d2[y]) { ans=d1[x]+z+d2[y]; pos1=x; pos2=y; } if(ans>d1[y]+z+d2[x]) { ans=d1[y]+z+d2[x]; pos1=y; pos2=x; } } //cout<<pos1<<" "<<pos2<<endl; answer=ans; } int way(int pos,int*p) { while(pos!=-1) { step.push_back(pos+1); pos=p[pos]; } return step.size(); } void output() { for(int i=num1-1;i>=0;i--) printf("%d ",step[i]); for(int i=num1;i<num2-1;i++) printf("%d ",step[i]); printf("%d\n",step[num2-1]); } int main() { #ifdef debug freopen("in.in","r",stdin); #endif // debug while(scanf("%d%d%d",&n,&s,&t)!=EOF) { cas++; if(cas!=1) printf("\n"); s--;t--; fast.clear(); step.clear(); ans.init(n); scanf("%d",&m); memset(p1,-1,sizeof(p1)); memset(p2,-1,sizeof(p2)); for(int i=0; i<m; i++) { int x,y,w; scanf("%d%d%d",&x,&y,&w); x--;y--; ans.AddEdge(x,y,w); ans.AddEdge(y,x,w); } scanf("%d",&k); for(int i=0; i<k; i++) { int x,y,w; scanf("%d%d%d",&x,&y,&w); x--;y--; fast.push_back(Edge(x,y,w)); fast.push_back(Edge(y,x,w)); } ans.dijkstra(s,d1,p1); ans.dijkstra(t,d2,p2); solve(); if(pos1!=-1) { num1=way(pos1,p1); num2=way(pos2,p2); output(); printf("%d\n",pos1+1); printf("%d\n",answer); } else { num1=way(t,p1); for(int i=num1-1;i>0;i--) printf("%d ",step[i]); printf("%d\n",step[0]); printf("Ticket Not Used\n"); printf("%d\n",answer); } } return 0; }
题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2369
题解:将路线分成三部分:s到a,a到b(a-b即为坐商业线),b到t。运行两次Dijkstra,求出s到每个点的最短距离d1和t到每个点的最短距离d2,枚举每条商业线a-b 则ans=min{d1[a]+w+d2[b],ans}(a,b可互换(无向边))ans初值为直接从s到t的最短路(也即不经过任何商业线的路径)。注意路径输出:由终点不断推向起点(挂了好几次)。