题目链接
题意
给定若干个城市,然后给出一个起点s和终点t,要求从起点到终点的最短路。
有所不同的是,可以任选一条路的长度打半折,要求这样以后的最短路。
题解
此题的第一个难点在于存边,由于给定的都是城市名,所以要用map把它转化成数字。
而如何求最短路,则可以先求出以s为起点到所有点的最短路d1[n],然后再求出以t为起点到所有点的最短路d2[n]。最后遍历一下所有边,总的最短路一定是d1[i]+d2[j]+dis(i,j)/2 。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <cmath>
using namespace std;
#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
#define next next_
typedef long long ll;
typedef unsigned long long ull;
const ll INF = 1e17;
const int inf = 0x3f3f3f3f;
const int maxn = 100005;
const int N = 105;
inline void read(ll &x) {
ll f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
ll n,m,tot,d[maxn],d1[maxn],d2[maxn];
vector<pair<ll,ll> >e1[maxn],e2[maxn];
map<string,ll> mp;
priority_queue<pair<ll,ll> >q;
ll ID(string s) {
if(mp[s]==0) {
mp[s] = ++tot;
}
return mp[s];
}
void dijk1(ll s,ll t) {
memset(d1,inf,sizeof(d1));
d1[s] = 0;
q.push(make_pair(-d1[s],s));
while(!q.empty()) {
ll now = q.top().second; q.pop();
for(int i=0;i<e1[now].size();i++) {
ll v = e1[now][i].first;
if(d1[v] > d1[now] + e1[now][i].second) {
d1[v] = d1[now] + e1[now][i].second;
q.push(make_pair(-d1[v],v));
}
}
}
}
void dijk2(ll s,ll t) {
memset(d2,inf,sizeof(d2));
d2[s] = 0;
q.push(make_pair(-d2[s],s));
while(!q.empty()) {
ll now = q.top().second; q.pop();
for(int i=0;i<e2[now].size();i++) {
ll v = e2[now][i].first;
if(d2[v] > d2[now] + e2[now][i].second) {
d2[v] = d2[now] + e2[now][i].second;
q.push(make_pair(-d2[v],v));
}
}
}
}
void init() {
for(int i=1;i<=n;i++) e1[i].clear(),e2[i].clear();
mp.clear();
tot = 0;
}
int main() {
while(~scanf("%lld%lld",&n,&m)) {
init();
string ss,tt;
for(int i=0;i<m;i++) {
string s1,s2;
ll z;
cin>>s1>>s2;
read(z);
ll t1 = ID(s1), t2 = ID(s2);
// cout<<t1<<" "<<t2<<endl;
e1[t1].push_back(make_pair(t2,z));
e2[t2].push_back(make_pair(t1,z));
}
cin>>ss>>tt;
ll s = ID(ss), t = ID(tt);
dijk1(s,t);
dijk2(t,s);
ll ans = 1e17;
for(int i=1;i<=tot;i++) {
for(int j=0;j<e1[i].size();j++) {
ll k1 = i, k2 = e1[i][j].first, z = e1[i][j].second;
ans = min(ans,d1[k1]+d2[k2]+z/2);
}
}
if(ans==INF) ans = -1;
cout<<ans<<endl;
}
return 0;
}