AcWing 1577. 条条大路通罗马
原题链接
中等
作者:
PASSIONNNN
,
2024-12-12 22:09:12
,
所有人可见
,
阅读 2
#include <iostream>
#include <cstring>
#include <unordered_map>
#include <vector>
using namespace std;
const int N = 210;
int n, m;
int w[N];
int d[N][N];
int dist[N], cnt[N], cost[N], sum[N], pre[N];
// 最短距离,最短路数量,最大点权,最小点数, 最短路径的前一个点
bool st[N];
string city[N];
unordered_map<string, int> mp;
void dijkstra()
{
memset(dist, 0x3f, sizeof dist);//先初始化,最短距离
dist[1] = 0, cnt[1] = 1;//一号点距离,根据题意初始化其他输出变量
for (int i = 0; i < n; i ++ )
{
int t = -1;
for (int j = 1; j <= n; j ++ )
if (!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;//找出最短距离的点,得到目前全局最短路径的点
st[t] = true;//完全固定
for (int j = 1; j <= n; j ++ )
if (dist[j] > dist[t] + d[t][j])//用t更新最短距离,通过t走向j
{//先列出能更新的所有东西,后面根据条件一点点删
dist[j] = dist[t] + d[t][j];
cnt[j] = cnt[t];//同一条路,路径相等
cost[j] = cost[t] + w[j];
sum[j] = sum[t] + 1;//多走了一个t
pre[j] = t;
}
else if (dist[j] == dist[t] + d[t][j])//最短路不止一条
{
cnt[j] += cnt[t];//不止一条的时候合并数量
if (cost[j] < cost[t] + w[j])//第二变量:最大点权
{
cost[j] = cost[t] + w[j];
sum[j] = sum[t] + 1;
pre[j] = t;
}
else if (cost[j] == cost[t] + w[j])
{
if (sum[j] > sum[t] + 1)//最少点数
{
sum[j] = sum[t] + 1;
pre[j] = t;
}
}
}
}
}
int main()
{
cin >> n >> m >> city[1];//城市总数,城市之间道路数量,初始城市名称
mp[city[1]] = 1;//给城市名和城市序号做映射
for (int i = 2; i <= n; i ++ )
{
cin >> city[i] >> w[i];//依次输入城市名和幸福感
mp[city[i]] = i;
}
memset(d, 0x3f, sizeof d);//给距离初始化
while (m -- )
{
string x, y;
int c;
cin >> x >> y >> c;//双向道路,地点1到地点2花费
int a = mp[x], b = mp[y];
d[a][b] = d[b][a] = min(d[a][b], c);//取最短路径
}
dijkstra();
int T = mp["ROM"];//终点是罗马
cout << cnt[T] << ' ' << dist[T] << ' ' << cost[T] << ' ' << cost[T] / sum[T] << endl;
//输出最小成本路线数,最小成本,幸福感,平均幸福感
vector<int> path;
for (int i = T; i != 1; i = pre[i]) path.push_back(i);
//输出路线,从结束位置每次往前找前驱
cout << city[1];
for (int i = path.size() - 1; i >= 0; i -- )
cout << "->" << city[path[i]];
cout << endl;
return 0;
}