返回目录
题意
有N个城市,M条无向边。现在需要从某个给定的起始城市出发(除了起始城市外,其他每个城市都有一个“幸福值”),前往名为“ROM”的城市。给出每条边所需要消耗的花费,求从起始城市出发,到达城市ROM所需要的最少花费,并输出最少花费的路径。如果这样的路径有多条,则选择幸福值最大的那条。如果还有多条,则选择平均值最大的那条,平均值即幸福值之和/路径上的城市数量。
样例(可复制)
6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1
//output
3 3 195 97
HZH->PRS->ROM
注意点
- 本题可以使用Dijkstra或Dijkstra+DFS的方式解决,笔者使用了前者。
- 相比普通的Dijkstra,本题在算法流程中还需要加入计算:①路径数量②最大幸福值③当前的路径上的顶点数④保存最优路径上的每个点的前驱节点
- 对于城市名字使用map<string,int>和map<int,string>在输入时就进行一一对应,也可以考虑使用hash存储编号
#include<bits/stdc++.h>
using namespace std;
const int N=220;
int n,m,ed;//城市数量,边数 ,ROM城市编号
int G[N][N];//图
//W为幸福值,dis为距离,C为累计的幸福值,num为路径数,pt为路径的点数,pre为前驱节点
int W[N],dis[N],C[N],num[N]={0},pt[N]={0},pre[N];
bool vis[N];//标记是否访问过
map<string,int> nametoid;
map<int,string> idtoname;
void Dijkstra(){
fill(dis,dis+N,INT_MAX);
fill(C,C+N,INT_MAX);
memset(vis,false,sizeof(vis));
dis[0]=0;
C[0]=0;//起点幸福值为0
num[0]=1;//路径初始为1
while(!vis[ed]){
int minn=INT_MAX,v;
for(int i=0;i<n;i++){//找最短路径
if(!vis[i]&&dis[i]<minn){
minn=dis[i];
v=i;
}
}
vis[v]=true;
for(int i=0;i<n;i++){
if(!vis[i]&&G[v][i]>0&&dis[i]>dis[v]+G[v][i]){
dis[i]=dis[v]+G[v][i];
pre[i]=v;
num[i]=num[v];
C[i]=C[v]+W[i];
pt[i]=pt[v]+1;
}else if(G[v][i]>0&&dis[i]==dis[v]+G[v][i]){
num[i]+=num[v];//想想为什么不是num[i]=num[v]+1
if(C[v]+W[i]>C[i]){//如果幸福值更大
pre[i]=v;
C[i]=C[v]+W[i];
pt[i]=pt[v]+1;
}else if(C[v]+W[i]==C[i]){//幸福值相等
double preavg=1.0*C[i]/pt[i];//之前的平均值
double nowavg=1.0*C[i]/(pt[v]+1);//现在的平均值
if(nowavg>preavg){
pre[i]=v;
pt[i]=pt[v]+1;
}
}
}
}
}
}
void printpath(int v){
if(v==0){
cout<<idtoname[0];
return;
}
printpath(pre[v]);
cout<<"->"<<idtoname[v];
}
int main(){
string name;
cin>>n>>m>>name;
nametoid[name]=0;
idtoname[0]=name;
for(int i=1;i<n;i++){
cin>>name>>W[i];
nametoid[name]=i;
idtoname[i]=name;
}
while(m--){
string a,b;
int dd;
cin>>a>>b>>dd;
G[nametoid[a]][nametoid[b]]=G[nametoid[b]][nametoid[a]]=dd;
}
ed=nametoid["ROM"];
Dijkstra();
printf("%d %d %d %d\n",num[ed],dis[ed],C[ed],C[ed]/pt[ed]);
printpath(ed);//递归打印路径
return 0;
}