Description
给出若干张机票的起点终点名称和价格,有一张机票打对折,给出起点终点,问最少花费
Input
多组用例,每组用例第一行两个整数n和m分别表示城市数和机票数,之后m行每行输入起点城市名称u和终点城市名称v以及机票价格c,最后输入起点名称和终点名称,以文件尾结束输入(2<=n<=1e5,0<=m<=5e5,0<=c<=1e5,城市名称不超过10个字符)
Output
对于每组用例,如果起点城市可以到终点城市则输出最少花费,否则输出-1
Sample Input
4 4
Harbin Beijing 500
Harbin Shanghai 1000
Beijing Chengdu 600
Shanghai Chengdu 400
Harbin Chengdu
4 0
Harbin Chengdu
Sample Output
800
-1
Solution
拿map把城市名称映射成数字编号,对原图以s为起点跑一遍最短路得到dis1[i]表示s到i的最短距离,对反图以e为起点跑一遍最短路得到dis2[i]表示e到i的最短距离,枚举每条边u->v,dis[u][v]表示u到v的距离,从dis1[u]+dis[u][v]/2+dis2[v]中选取一个最小值即为答案
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 1e12
#define maxn 555555
struct edge
{
int to,next,cost;
}g[maxn];
int head[maxn],tol;
int dis[maxn];//所有点到起点的最短距离
void init()//初始化
{
memset(head,-1,sizeof(head));
tol=0;
}
void add(int u,int v,int c)//单向边,从u到v,权值为c
{
g[tol].cost=c;
g[tol].to=v;
g[tol].next=head[u];
head[u]=tol++;
}
ll dis1[maxn],dis2[maxn];
void spfa(int s)//单源最短路,s是起点
{
bool vis[maxn];
memset(vis,0,sizeof(vis));
queue<int>que;
for(int i=0;i<maxn;i++)dis2[i]=INF;
dis2[s]=0,vis[s]=1;
que.push(s);
while(!que.empty())
{
int u=que.front();que.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=g[i].next)
{
int v=g[i].to,c=g[i].cost;
if(dis2[v]>dis2[u]+c)
{
dis2[v]=dis2[u]+c;
if(!vis[v])vis[v]=1,que.push(v);
}
}
}
}
map<string,int>M;
int n,m,E[maxn][3];
int get(string s)
{
if(M.find(s)!=M.end())return M[s];
M[s]=++n;
return n;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
M.clear();
n=0;
string a,b;
for(int i=1;i<=m;i++)
{
int u,v,c;
cin>>a>>b>>c;
u=get(a),v=get(b);
E[i][0]=u,E[i][1]=v,E[i][2]=c;
add(u,v,c);
}
cin>>a>>b;
int s=get(a),e=get(b);
spfa(s);
for(int i=1;i<=n;i++)dis1[i]=dis2[i];
init();
for(int i=1;i<=m;i++)
{
int u=E[i][0],v=E[i][1],c=E[i][2];
add(v,u,c);
}
spfa(e);
ll ans=INF;
for(int i=1;i<=m;i++)
{
int u=E[i][0],v=E[i][1],c=E[i][2];
ans=min(ans,dis1[u]+c/2+dis2[v]);
}
if(ans==INF)printf("-1\n");
else printf("%lld\n",ans);
}
return 0;
}