原题链接:http://pat.zju.edu.cn/contests/pat-a-practise/1087
此题和1018似乎很像,较繁琐:
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define INF 0x7fffffff
//BFS找到总计路数
int bfsnm(vector<vector<int>> &preCityCostMinVec, int start, int end)
{
queue<int> que;
que.push(end);
while(que.front() != start)
{
for(int i=0; i < preCityCostMinVec[que.front()].size(); i++)
{
que.push(preCityCostMinVec[que.front()][i]);
}
que.pop();
}
return que.size();
}
int main()
{
int n, k, val;
string city, cityN, cityS;
vector<int> hVec;//记录城市的幸福感
vector<int> preCityIdVec;//记录到当前城市最佳道路的唯一前驱
vector<int> preCityNumVec;//记录到当前城市最佳道路上城市数量
vector<int> accHappinessVec;//记录到当前城市最佳道路上累计的幸福感
set<int> visitedSet;//已访问城市集
set<int> unvisitedSet;//未访问城市集
map<string,int> idmap;//城市名称及id对应map
vector<string> strCity;
vector<vector<int>> roadLenBtwCityVec;//记录城市之间的路的Cost
vector<vector<int>> preCityCostMinVec;//记录到某个城市cost最少的所有道路中这个城市的前驱
cin>>n>>k>>cityS;
hVec.resize(n);
strCity.resize(n);
preCityIdVec.resize(n);
preCityNumVec.resize(n);
accHappinessVec.resize(n);
preCityCostMinVec.resize(n);
roadLenBtwCityVec.resize(n);
for(int i=0; i<n; i++)
{
if(i == 0)
{
city = cityS;//初始城市无幸福感,且不参与平均幸福感的计算
val = 0;
}
else
{
cin>>city>>val;
}
hVec[i] = val;
strCity[i] = city;
preCityNumVec[i] = 1;
accHappinessVec[i] = val;
roadLenBtwCityVec[i].resize(n);
idmap.insert(pair<string,int>(city,i));
for(int j=0; j<n; j++)
{
roadLenBtwCityVec[i][j] = INF;
}
roadLenBtwCityVec[i][i] = 0;//结点到自身cost为0
unvisitedSet.insert(i);
}
for(int i=0,x,y; i<k; i++)
{
cin>>city>>cityN>>val;
x = idmap.find(city)->second;
y = idmap.find(cityN)->second;
roadLenBtwCityVec[x][y] = val;
roadLenBtwCityVec[y][x] = val;
}
int start = 0;
int end = idmap.find("ROM")->second;
preCityIdVec[start] = -1;
preCityNumVec[start] = 0;
visitedSet.insert(start);
unvisitedSet.erase(unvisitedSet.find(start));
while(visitedSet.find(end) == visitedSet.end())//dijkstra扩展结点
{
int pre,next,count = 0;
int minLen = INF;
for(auto vicity = visitedSet.begin(); vicity != visitedSet.end(); vicity++)
for(auto uvicity = unvisitedSet.begin(); uvicity != unvisitedSet.end(); uvicity++)
{
if(roadLenBtwCityVec[*vicity][*uvicity] < minLen)
{
if(roadLenBtwCityVec[start][*vicity] + roadLenBtwCityVec[*vicity][*uvicity] < minLen)
{
pre = *vicity;
next = *uvicity;
preCityCostMinVec[next].clear();
preCityCostMinVec[next].push_back(pre);
minLen = roadLenBtwCityVec[start][*vicity] + roadLenBtwCityVec[*vicity][*uvicity];
}
else if(roadLenBtwCityVec[start][*vicity] + roadLenBtwCityVec[*vicity][*uvicity] == minLen && *uvicity == next)
{//到某个城市cost最少的所有道路都需要记录
preCityCostMinVec[next].push_back(*vicity);
if((accHappinessVec[*vicity] > accHappinessVec[pre]) ||
(accHappinessVec[*vicity] == accHappinessVec[pre] && preCityNumVec[*vicity] < preCityNumVec[pre]))
{
pre = *vicity;
next = *uvicity;
}
}
}
}
visitedSet.insert(next);
unvisitedSet.erase(unvisitedSet.find(next));
roadLenBtwCityVec[start][next] = roadLenBtwCityVec[next][start] = minLen;//更新开始城市到新扩展城市的cost
preCityIdVec[next] = pre;//记录最佳道路上当前城市的前驱
preCityNumVec[next] = 1 + preCityNumVec[pre];//开始城市到当前城市的最佳道路上累计的城市数量
accHappinessVec[next] = hVec[next] + accHappinessVec[pre];//记录最佳道路上到当前城市时累计幸福感
}
cout<<bfsnm(preCityCostMinVec,start,end)<<" "<<roadLenBtwCityVec[start][end]<<" "<<accHappinessVec[end]<<" "<<accHappinessVec[end]/preCityNumVec[end]<<endl;
vector<string> citys;
for(int i=end; i!=-1; i=preCityIdVec[i])
{
citys.push_back(strCity[i]);
}
for(int i=citys.size()-1; i>0; i--)
{
cout<<citys[i]<<"->";
}
cout<<"ROM"<<endl;
}