pat 1087 最短路

#include<algorithm>
#include<map>
#include<vector>
#include<string>
#include<iostream>
#include<stack>
using namespace std;
 
#define max 203
#define inf 0x3f3f3f3f
int dis[max][max]={0};
int n=0;
int visited[max]={0};
int pre[max]={0};
int same[max]={0};
int happies[max]={0};
int final_happies[max]={0};
int step[max]={0};
map<int,string> city_name;
map<string,int> city_num;
stack<string> ans;
void dijstrak(int s)//s是起点
{  
    same[0]=1;
    visited[s]=1;
    for(int i=0;i<n;i++)
    {
         int min=inf;
         int mark=-1;
         for(int j=0;j<n;j++)
         {//找到离起点距离最小的
             if(visited[j]==0&&dis[s][j]<min)
             {
                min=dis[s][j];
                mark=j;
             }
         }
         if(mark==-1)
             return ;
         visited[mark]=1;//marked
         for(int i=0;i<n;i++)
         {//updata
             if(visited[i]==1)
                 continue;
             int p_dis=dis[s][i];
             int n_dis=dis[s][mark]+dis[mark][i];
            if(p_dis>n_dis) //如果新的距离(有了最小值节点mark之后的更新导致)小于之前的距离
            {   same[i]=same[mark];
                dis[s][i]=dis[s][mark]+dis[mark][i];
                pre[i]=mark;
                final_happies[i]=final_happies[mark]+happies[i];
                step[i]=step[mark]+1;
            }
            if(p_dis==n_dis)
            {
                same[i]+=same[mark];
                if(final_happies[i]<final_happies[mark]+happies[i])//现在的顶点权值较大
                {
                    pre[i]=mark;
                    final_happies[i]=final_happies[mark]+happies[i];
                    step[i]=step[mark]+1;
                }
                if(final_happies[i]==final_happies[mark]+happies[i])//如果顶点权值相等,第三步判断平均顶点权值
                {
                   if(step[i]>(step[mark]+1)) //之前的步数多,那就更新
                   {
                       pre[i]=mark;
                       step[i]=step[mark]+1;
                   }
                }
            }
 
            }
                
         }
    }
 
int main()
{
    //初始化距离都为无穷大
    for(int i=0;i<max;i++)
        for(int j=0;j<max;j++){
            dis[i][j]=inf;
            dis[j][i]=inf;
            dis[i][i]=inf;
            dis[j][j]=inf;
    }
   int k=0;
   string s;
   cin>>n>>k>>s; //n城市数,k路数,s开始城市
   city_name[0]=s;
   string citystr;
   int happy=0;
   //存城市的幸福值:
   for(int i=1;i<n;i++)
   {
    cin>>citystr>>happy;
    city_name[i]=citystr;
    city_num[citystr]=i;
    happies[i]=happy;
    final_happies[i]=happy;
    step[i]=1; //总步数
    same[i]=1; //相同最短路数量
   }
   string city1,city2;
   int cost=0;
   //存城市之间的距离
   for(int i=0;i<k;i++){
     cin>>city1>>city2>>cost;
     int j=city_num[city1];
     int b=city_num[city2];
     dis[j][b]=cost;
     dis[b][j]=cost;
   }
 
   dijstrak(0);   
 
   int ROM_num=city_num["ROM"];
   int index=ROM_num;
   string path;
   path+=s;//"HZH"
   ans.push("ROM");
   while(pre[index]!=0)//不断找前驱,然后就入栈
   {//入栈其实是倒着的路
     string pathcity=city_name[pre[index]];
     ans.push(pathcity);
     index=pre[index];
   }
   //出栈
   while(!ans.empty()){
       path+="->";
       path+=ans.top();
       ans.pop();
   }
   cout<<same[ROM_num]<<" "<<dis[0][ROM_num]<<" "<<final_happies[ROM_num]<<" "<<final_happies[ROM_num]/step[ROM_num]<<endl;
   cout<<path<<endl;
  return 0;
}

 

posted @ 2021-01-10 16:26  然终酒肆  阅读(68)  评论(0编辑  收藏  举报