2017CCCC天梯赛 L3-2 周游世界

考试的时候这道题写了超久……中间推翻了一开始直连相邻边的想法 改成全部连边 总算过了……没有白费考前狂练多关键字最短路的成果……然而 物理题没做出来 拖后腿了。

大概思路嘛,姥姥出的题,肯定是多关键字最短路233  然后我一开始是相邻连边,但是后来发现一个路径不好记录,而且点数什么的也不好设置,无法转化。后来才发现完全

可以同一条线路全部连边,有重边的话 最短路算法是不影响的。(想到了以前某场CF gym里的题) 然后就想到了 记录路径也不难了。。然后终于A了QAQ 其实floyed应该也够了…… 我用了dijkstra。。。

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
const int inf=(1<<30)-1;
int n;
set<int> s[maxn];
int m,a[maxn];
map<string,int> m1;
map<int,string> m2;
struct data{
  int to,v,w;
};
vector<data> G[maxn];
int d[maxn],vis[maxn];
int path[maxn];
int num[maxn];
int pp[maxn];
int tot=0;
struct node{
  int u,d,num;
  bool operator <(const node &b) const {
    return (d==b.d)?num>b.num:d>b.d;
  }
};
void dij(int s)
{
  priority_queue<node> q;
  for(int i=0;i<=maxn-1;i++) d[i]=inf;
  memset(vis,0,sizeof(vis));
  d[s]=0;
  memset(path,0,sizeof(path));
  memset(pp,0,sizeof(pp));
  path[s]=-1;
  num[s]=1;
  q.push((node){s,d[s],num[s]});
  while(!q.empty())
  {
    node x=q.top();q.pop();
    int u=x.u;
    if(vis[u]) continue;
    vis[u]=1;
    for(int i=0;i<G[u].size();i++)
    {
      data &e=G[u][i];
      int to=e.to,v=e.v,w=e.w;
      //printf("%d %d\n",to,v);
      if(d[to]>d[u]+v)
      {
        d[to]=d[u]+v;
        num[to]=num[u]+1;
        q.push((node){to,d[to],num[to]});
        path[to]=u;
        //printf("%d %d %d %d\n",u,to,num[u],num[to]);
        pp[to]=w;
      }
      else if(d[to]==d[u]+v)
      {
        if(num[to]>num[u]+1)
        {
          num[to]=num[u]+1;
          q.push((node){to,d[to],num[to]});
          path[to]=u;
          pp[to]=w;
        }
      }
    }
  }  
}
void dfs(int x)
{
  if(path[x]==-1) return;
  dfs(path[x]);
  cout<<"Go by the line of company #"<<pp[x]<<" from "<<m2[path[x]]<<" to "<<m2[x]<<"."<<endl;
}
int main()
{
  scanf("%d",&n);
  for(int k=1;k<=n;k++)
  {
    
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
      string str;
      cin>>str;
      if(!m1[str]) m1[str]=++tot,m2[m1[str]]=str;a[i]=m1[str];
    }
    for(int i=1;i<=m;i++)
    for(int j=1;j<i;j++)
    {
        int x=a[i],y=a[j];
        G[x].push_back((data){y,i-j,k});
        G[y].push_back((data){x,i-j,k});
    }  
  }
  
  int Q;
  scanf("%d",&Q);
  while(Q--)
  {
    string s1,s2;
    cin>>s1>>s2;
    int x=m1[s1],y=m1[s2];
    dij(x);
    if(d[y]!=inf)printf("%d\n",d[y]),dfs(y);
    else puts("Sorry, no line is available.");
  }
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值