【1087 30 Dijkstra】 All Roads Lead to Rome
传送门
题意
给定\(n\)个城市,\(m\)条⽆向边,从某个给定的起始城市出发,前往名为ROM的城市。每个城市 (除起始城市)都有一个点权,每条边有边权。求从起点到ROM所需要的最少花费,并输出其路径。如果路径有多条,给出幸福值最大的那条。如果仍然不唯一,选择路径上的城市平均幸福值最大的那条路径
数据范围
\(n\leq 200\)
题解
Dijkstra求最短路同时更新额外信息即可pre记录最路径用于输出
Code
#include<bits/stdc++.h>
using namespace std;
const int N=210,INF=0x3f3f3f3f;
vector<int>pre,path;
bool st[N];
int h[N],g[N][N],d[N],sum[N],num[N],minpath[N];
int n,k,s,e,cnt,ans;
map<string,int>mp;
map<int,string>unmp;
int get(string s){
if(mp[s]==0) { mp[s]=++cnt;unmp[cnt]=s;}
return mp[s];
}
void dijkstra(){
d[s]=0,num[s]=0,sum[s]=h[s],minpath[s]=1;
for(int i=0;i<cnt;i++){
int t=-1;
for(int j=1;j<=cnt;j++)
if(!st[j] && (t==-1||d[t]>d[j])) t=j;
if(t==-1) return;
st[t]=1;
for(int j=1;j<=cnt;j++){
if(d[j] > d[t]+g[t][j]){
pre[j]=t;
d[j]=d[t]+g[t][j];
num[j]=num[t]+1;
sum[j]=sum[t]+h[j];
minpath[j]=minpath[t];
}
else if(d[j] == d[t]+g[t][j]) {
minpath[j]+=minpath[t];
if(sum[j]<sum[t]+h[j] || sum[j]==sum[t]+h[j] && num[j]>num[t]+1){
pre[j]=t;
num[j]=num[t]+1;
sum[j]=sum[t]+h[j];
}
}
}
}
}
int main(){
memset(g,0x3f,sizeof g);
memset(d,0x3f,sizeof d);
string t; cin>>n>>k>>t;
s=get(t);
for(int i=1;i<n;i++) {
int hap; cin>>t>>hap;
int id=get(t);
if(t=="ROM") e=id;
h[id]=hap;
}
while(k--){
string a,b; int dis; cin>>a>>b>>dis;
int u=get(a),v=get(b);
g[u][v]=g[v][u]=dis;
}
pre.resize(cnt+1);
dijkstra();
int now=e;
while(now!=s){
path.push_back(now);
now=pre[now];
}
path.push_back(s);
reverse(path.begin(),path.end());
cout<<minpath[e]<<' '<<d[e]<<' '<<sum[e]<<' '<<(sum[e]/num[e])<<endl;
for(int i=0;i<path.size();i++) cout<<(i==0?"":"->")<<unmp[path[i]];
}

浙公网安备 33010602011771号