这题的关键是把车站的名字转化为点的编号。我用的是map。声明一个map<string,int> st,然后按照字符串出现的次序给st赋值。例如:st[s1]=2;代表这字符串s1出现的次序是2。出现过的已经被标记。不会重复。接下来用模版就好。不过有一点要注意的是当起点和终点一样是,要输出0。
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<algorithm> using namespace std; //在主函数中Map初始化为INF const int N = 160, INF =0x3f3f3f3f; int dist[N], Map[N][N], pre[N]; //dist表示i到s的最短距离,Map记录图,pre记录前驱 bool p[N];//标记点是否已经被选择 void Dijkstra(int n,int s) { int i,j,k, MIN; for(i=1; i<=n; i++) //初始化 { p[i]=0; if(i!=s) { dist[i]= Map[s][i]; pre[i]=s; } } dist[s]=0; p[s]=1; for(i=1; i<n; i++) //循环n-1次 { MIN=INF; k=0; for(j=1; j<=n; j++) { if(!p[j]&&dist[j]<MIN) { MIN= dist[j]; k=j; } } if(!k) return ;//没有点可以扩展 p[k]=1; //将k从Vb中除去,加入Va for(j=1; j<=n; j++) { if(!p[j]&&Map[k][j]!=INF&&dist[j]>dist[k]+Map[k][j]) { dist[j]= dist[k] + Map[k][j]; pre[j]=k; } } } } void init() { for(int i=0;i<=N;i++) for(int j=0;j<=N;j++) Map[i][j]=INF; } map<string,int> st; int main() { //freopen("test.txt","r",stdin); int n,i,j,k; char s1[35],s2[35]; while(scanf("%d",&n)!=EOF) { if(n==-1) break; scanf("%s%s",s1,s2); if(strcmp(s1,s2)==0) { for(i=0;i<n;i++) scanf("%s%s%d",s1,s2,&k); printf("0\n"); continue; } init(); st.clear(); st[s1]=1; st[s2]=2; j=2; for(i=0;i<n;i++) { scanf("%s%s%d",s1,s2,&k); if(st[s1]==0) st[s1]=++j; if(st[s2]==0) st[s2]=++j; if(st[s1]==st[s2]) continue; Map[st[s2]][st[s1]]=Map[st[s1]][st[s2]]=min(k,Map[st[s1]][st[s2]]); } Dijkstra(j,1); if(dist[2]<INF) printf("%d\n",dist[2]); else printf("-1\n"); } return 0; }
时间: 2024-10-15 22:38:44