1087. All Roads Lead to Rome (30)

#include<unordered_map>
#include<bitset>
#include<iostream>
#include<string>
#include<vector>
using namespace std;
const int N=300;
int pos;
string name[300];
int s2i(string s)
{
  static  unordered_map<string,int>nth;
  auto it=nth.find(s);
  if(it!=nth.end())
    return it->second;
  else{
    name[pos]=s;
    nth[s]=pos;
    return pos++; }
}
struct node{int to,len;node(int a,int b):to(a),len(b){}};
vector<node>ed[N];
int dis[N],pre[N],allval[N],used[N],num[N],cnt[N];
int src,dst,val[N];
void dijkstra()
{
  fill_n(dis,N,1<<30);
  dis[src]=0;
  allval[src]=val[src];
  num[src]=0;
  cnt[src]=1;
  while(true)
    {
      
      int next=-1;
      for(int mmin=1<<30,i=0;i<pos;++i)
	if(!used[i]&&dis[i]<mmin) mmin=dis[next=i];
      if(next==-1)break;
      used[next]=true;
      for(auto x:ed[next])
	if(!used[x.to])
	  {
	    if(dis[x.to]>dis[next]+x.len)
	      {
		cnt[x.to]=cnt[next];
		dis[x.to]=dis[next]+x.len;
		pre[x.to]=next;
		allval[x.to]=allval[next]+val[x.to];
		num[x.to]=num[next]+1;
	      }else if(dis[x.to]==dis[next]+x.len)
	      {
		cnt[x.to]+=cnt[next];
		if(allval[x.to]<allval[next]+val[x.to]||
		   allval[x.to]==allval[next]+val[x.to]&&
		   (num[x.to]>num[next]+1))
		  {
		    pre[x.to]=next;
		    allval[x.to]=allval[next]+val[x.to];
		    num[x.to]=num[next]+1;
		  }//if
	      }//else if
	  }//if
    }//while
}
void path(int k){
  if(k!=src) path(pre[k]);
  static int first=0;
  cout<<(first++?"->":"")<<name[k];
}
int main(){
  dst=s2i("ROM");
  int n,k;
  string sa,sb;
  cin>>n>>k>>sa;
  src=s2i(sa);
  for(int i=1,tmp;i<n;++i)
    {cin>>sa>>tmp; val[s2i(sa)]=tmp; }
  for(int i=0,len,t1,t2;i<k;++i){
    cin>>sa>>sb>>len;
    t1=s2i(sa),t2=s2i(sb);
    ed[t1].emplace_back(t2,len);
    ed[t2].emplace_back(t1,len);
  }
  dijkstra();
  printf("%d %d %d %d\n",cnt[dst],dis[dst],allval[dst],allval[dst]/num[dst]);
  path(dst);
}
dijkstra算法,不过平常在松弛路径是只要保持pre,dis,used就行,这里还要保持最短路径数cnt,最短路径上最多城市数num,最短路径上最大累计happy值allval,其他的没什么,注意cnt的更新方式即可
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值