给一个无向图,有的边是特殊边,最多可以取一条特殊边,求最短路,并且输出路径。
这样考虑,加入所有非特殊边,求出每个点到起点和终点的最短路。
然后加入特殊边的时候,如果取当前这条特殊边,那么答案会是两点预处理路径长度加上该边长。直接保存最小答案即可。
不过注意输出的格式还有一些其他的问题,还有加特殊边的时候要考虑是那一端连接起点终点。。。。
召唤代码君:
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #define maxn 222000 using namespace std; struct heapnode{ int D,U; bool operator < (heapnode V) const{ return D>V.D; } }; const int inf=~0U>>3; int to[maxn],next[maxn],c[maxn],first[maxn],edge; int dis1[maxn],dis2[maxn],from1[maxn],from2[maxn]; bool done[maxn]; int n,m,s,t,k,ans,len; void _init() { edge=-1; for (int i=1; i<=n; i++) first[i]=-1,dis1[i]=inf,dis2[i]=inf,from1[i]=-1,from2[i]=-1; } void addedge(int U,int V,int W) { edge++; to[edge]=V,c[edge]=W,next[edge]=first[U],first[U]=edge; edge++; to[edge]=U,c[edge]=W,next[edge]=first[V],first[V]=edge; } void dijkstra(int nd,int dis[],int from[]) { for (int i=1; i<=n; i++) done[i]=false; priority_queue<heapnode> Q; Q.push((heapnode){0,nd}),dis[nd]=0; while (!Q.empty()) { heapnode cur=Q.top(); Q.pop(); if (done[cur.U]) continue; else done[cur.U]=true; for (int i=first[cur.U]; i!=-1; i=next[i]) if (dis[cur.U]+c[i]<dis[to[i]]) dis[to[i]]=dis[cur.U]+c[i],from[to[i]]=cur.U,Q.push((heapnode){dis[to[i]],to[i]}); } } void _input() { int U,V,W; scanf("%d",&m); while (m--) { scanf("%d%d%d",&U,&V,&W); addedge(U,V,W); } dijkstra(s,dis1,from1); dijkstra(t,dis2,from2); } void output(int cur) { if (cur==-1) return ; output(from1[cur]); printf("%d ",cur); } int main() { int U,V,W,UU,VV,T=0; while (scanf("%d%d%d",&n,&s,&t)!=EOF) { if (T++) puts(""); _init(); _input(); UU=-1,len=dis1[t]; scanf("%d",&m); while (m--) { scanf("%d%d%d",&U,&V,&W); if (dis1[U]+dis2[V]+W<len) len=dis1[U]+dis2[V]+W,UU=U,VV=V; if (dis1[V]+dis2[U]+W<len) len=dis1[V]+dis2[U]+W,UU=V,VV=U; } if (UU==-1) { output(from1[t]); printf("%d Ticket Not Used %d ",t,len); } else { output(UU); printf("%d",VV); for (int k=VV; from2[k]!=-1; k=from2[k]) printf(" %d",from2[k]); printf(" %d %d ",UU,len); } } return 0; }