卧槽。。。。最近刷的cf上有最短路,本来想拿这题复习一下。。。。
题意就是在输出最短路的情况下,经过每个节点会增加税收,另外要字典序输出,注意a到b和b到a的权值不同
然后就是处理字典序的问题,当松弛时发现相同值的时候,判断两条路径的字典序
代码
#include "stdio.h" const int MAXN=110; const int INF=10000000; bool vis[MAXN]; int pre[MAXN]; int cost[MAXN][MAXN],lowcost[MAXN],b1[MAXN]; int road[MAXN]; using namespace std; int cmp(int a,int b,int c) { int i,len1,len2,j; int p1[MAXN],p2[MAXN]; int cur=a; pre[a]=b; len1=0; while(cur!=-1) { p1[len1++]=cur; cur=pre[cur]; } len2=0; cur=a; pre[a]=c; while(cur!=-1) { p2[len2++]=cur; cur=pre[cur]; } for(i=len1-1,j=len2-1;i>=0&&j>=0;i--,j--) { if(p1[i]>p2[j]) return c; if(p1[i]<p2[j]) return b; } if(i==-1) return b; if(j==-1) return c; } void dijkstra(int beg,int n) { int ans; int k=0; for(int i=0; i<n; i++) { lowcost[i]=cost[beg][i]; vis[i]=false; pre[i]=-1; } for(int j=0; j<n; j++) { int k; int min=INF; for(int i=0; i<n; i++) if(!vis[i]&&lowcost[i]<min) { min=lowcost[i]; k=i; } if(k==-1) break; vis[k]=true; for(int i=0; i<n; i++) { if(cost[k][i]==INF) continue; if(!vis[i]&&lowcost[k]+cost[k][i]+b1[k]<lowcost[i]) { lowcost[i]=lowcost[k]+cost[k][i]+b1[k]; pre[i]=k; } else if(!vis[i]&&lowcost[k]+cost[k][i]+b1[k]==lowcost[i]) pre[i]=cmp(i,pre[i],k); } } } void print(int cur) { if(pre[cur]!=-1) print(pre[cur]); printf("-->%d",cur+1); } int main() { int n,i,j; int a,b,c; int ans,len; while(scanf("%d",&n)==1,n) { for(i=0; i<n; i++) { for(j=0; j<n; j++) { scanf("%d",&cost[i][j]); if(cost[i][j]==-1) cost[i][j]=INF; } } for(i=0; i<n; i++) scanf("%d",&b1[i]) ; while(scanf("%d%d",&a,&b)==2) { if(a==-1&&b==-1) break; a-=1; b-=1; len=0; dijkstra(a,n); ans=lowcost[b]; printf("From %d to %d :\nPath: %d",a+1,b+1,a+1); if(a!=b) print(b); printf("\n"); printf("Total cost : %d\n\n",ans); } } return 0; }
这里有一个小插曲,这题和zoj某题一样,搜索hdoj题号,出来的是floyd和dij上面暴力的解法,搜索zoj题号,出来的是dij+dfs解法,引人深思。。。