题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1385
题目大意:啊,写题目大意好烦啊,不想写了。哎,还是写吧。这道题的意思就是给你所有城市到其他城市的道路成本和经过每个城市的城市税,给你很多组城市,要求你找出每组城市间的最低运输成本并且输出路径,如果有多条路径则输出字典序最小的 的那条路径。注意,起点城市和终点城市不需要收城市税。
这道题我是用dijkstra写的,其实这种需要输出字典序路径的题目用floyd写的话会简单很多,不过用floyed写的话就有很多东西学不到。我在这只讲解如何用dijkstra实现。
代码:
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define maxn 105 #define N 50 int path[maxn],mp[maxn][maxn],tax[maxn],vis[maxn],n,dis[maxn]; int len; void dfs(int k,char s[]) { if(k==-1) return ; dfs(path[k],s); s[len++]=k+'0'; } int cmp(int re,int now) { char s1[N],s2[N]; len=0; dfs(re,s1);//将起点到re的最短路径储存 s1[len]=0; len=0; dfs(now,s2);//将起点到u的最短路径储存 s2[len++]=re+'0';//连接re点 s2[len]=0; if(strcmp(s1,s2)>0)//比较两条最短路径字典序大小 return 1; return 0; } void djk(int st,int ed){ int i,j,k; for(i=1;i<=n;i++){ dis[i]=mp[st][i]+tax[i];//将边权与点权相加,视为经过i号城市的代价 if(i==st) continue; if(dis[i]<inf) path[i]=st; } for(i=0;i<n-1;i++){ int mi=inf,u; for(j=1;j<=n;j++){ if(dis[j]<mi&&!vis[j]){ mi=dis[j]; u=j; } } vis[u]=1; for(k=1;k<=n;k++){ if(mp[u][k]<inf){ if(dis[k]>dis[u]+mp[u][k]+tax[k]){ dis[k]=dis[u]+mp[u][k]+tax[k]; path[k]=u; } else if(dis[k]==dis[u]+mp[u][k]+tax[k]&&cmp(k,u)){//若有多条最短路径进行字典序大小判断 path[k]=u;//注意比较最短路径大小不能之比较某一个点,要比较整条路径 } } } } } void show(int v,int st) { if(v==st) { cout<<v; return ; } show(path[v],st); cout<<"-->"<<v; } int main() { int i,j,k; while(cin>>n){ for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ cin>>mp[i][j];//输入道路成本 } } for(i=1;i<=n;i++){ cin>>tax[i];//输入每个城市的城市税 } for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ if(mp[i][j]==-1) mp[i][j]=inf;//-1的话不好进行判断,因此将其赋值为inf } } int x,y; while(cin>>x>>y&&(x!=-1||y!=-1)){ memset(vis,0,sizeof(vis)); memset(path,-1,sizeof(path)); djk(x,y); cout<<"From "<<x<<" to "<<y<<" :"<<endl; cout<<"Path: "; show(y,x); cout<<endl; cout<<"Total cost : "<<dis[y]-tax[y]<<endl;//减去终点城市的城市税 cout<<endl; } } }