题目:http://acm.hdu.edu.cn/showproblem.php?pid=3499
题意:给定一个有向带权图,点数n <= 1e5 边数 m <= 5 * 1e5, 可以选择任意一条边将其权值减半, 求s到t的最短路。
题意:给定一个有向带权图,点数n <= 1e5 边数 m <= 5 * 1e5, 可以选择任意一条边将其权值减半, 求s到t的最短路。
解法: 做两遍单源最短路, 一遍正向,一遍反向,枚举每条边<u, v>, 将其权值减半,所求答案即为min{dis[s → u] + dis[t → v] + w / 2}, 复杂度为最短路复杂度。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
using namespace std;
#define mp make_pair
#define se second
#define fi first
const int N = 100005;
const int M = 500005;
const int C = 62;
const long long INF = 1LL << 60;
typedef long long LL;
typedef pair<LL, int> P;
int n, m;
int map[256];
void init() {
for (int i = 0; i < 26; i++)
map[i + 'A'] = i;
for (int i = 0; i < 26; i++)
map[i + 'a'] = i + 26;
for (int i = 0; i < 10; i++)
map[i + '0'] = i + 52;
}
struct Edge {
Edge* next;
int v, w;
void init(int a, int b, Edge* e) {
next = e, v = a, w = b;
}
};
struct Dijkstra {
Edge E[M], * head[N];
priority_queue<P, vector<P>, greater<P> > pq;
LL dis[N];
int tot;
void init() {
for (int i = 0; i < n; i++)
head[i] = 0;
tot = 0;
}
void add(int u, int v, int w) {
E[tot].init(v, w, head[u]);
head[u] = &E[tot++];
}
void solve(int s) {
for (int i = 0; i < n; i++)
dis[i] = INF;
dis[s] = 0LL;
pq.push(mp(0LL, s));
while (!pq.empty()) {
P cur = pq.top();
pq.pop();
int u = cur.se;
if (cur.fi != dis[u]) continue;
for (Edge* e = head[u]; e; e = e->next) {
int v = e->v;
if (dis[v] > dis[u] + e->w) {
dis[v] = dis[u] + e->w;
pq.push(mp(dis[v], v));
}
}
}
}
}G1, G2;
struct Trie {
int ch[N][C], val[N];
int sz, id;
void init() {
sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
id = 0;
}
int find(char* s) {
int u = 0;
for (int i = 0; s[i]; i++) {
int c = map[s[i]];
if (!ch[u][c]) {
memset(ch[sz], 0, sizeof(ch[sz]));
val[sz] = -1;
ch[u][c] = sz++;
}
u = ch[u][c];
}
if (val[u] == -1)
val[u] = id++;
return val[u];
}
}T;
char u[100], v[100];
int main() {
int w;
init();
while (~scanf("%d%d", &n, &m)) {
T.init();
G1.init(), G2.init();
for (int i = 0; i < m; i++) {
scanf("%s%s%d", u, v, &w);
int a1 = T.find(u), a2 = T.find(v);
G1.add(a1, a2, w);
G2.add(a2, a1, w);
}
scanf("%s%s", u, v);
int s = T.find(u), t = T.find(v);
G1.solve(s);
G2.solve(t);
LL ans = INF;
for (int i = 0; i < n; i++)
for (Edge* e = G1.head[i]; e; e = e->next) {
int v = e->v;
ans = min(ans, G1.dis[i] + G2.dis[v] + (e->w / 2));
}
if (ans != INF)
printf("%I64d\n", ans); // hdu写法
else
puts("-1");
}
return 0;
}