数据范围很大,然而 n 很小
可以料想最短路树也是很小的
求最短路树,枚举最短路树上的树边,dijkstra 即可
代码:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
const int MAXN = 255, MAXM = 250005;
struct EDGE{
int nxt, to;
ll val;
EDGE(int NXT = 0, int TO = 0, ll VAL = 0ll) {nxt = NXT; to = TO; val = VAL;}
}edge[MAXM << 1];
int n, m, totedge = 1;
int head[MAXN], pre[MAXN], frm[MAXN];
bool vis[MAXN];
ll org, ans, dst[MAXN];
priority_queue<pair<ll,int> > q;
inline void add(int x, int y, ll v) {
edge[++totedge] = EDGE(head[x], y, v);
head[x] = totedge;
return;
}
inline void dij() {
for(int i = 1; i <= n; ++i) dst[i] = 2000000000000000;
dst[1] = 0ll;
q.push(make_pair(0, 1));
while(!q.empty()) {
int x = q.top().second; q.pop();
if(vis[x]) continue;
vis[x] = true;
for(int i = head[x]; i; i = edge[i].nxt) {
register int y = edge[i].to;
if(dst[y] > dst[x] + edge[i].val) {
dst[y] = dst[x] + edge[i].val;
frm[y] = i;
pre[y] = x;
q.push(make_pair(-dst[y], y));
}
}
}
org = dst[n];
return;
}
inline void dij2() {
for(int i = 1; i <= n; ++i) dst[i] = 2000000000000000, vis[i] = false;
dst[1] = 0ll;
q.push(make_pair(0, 1));
while(!q.empty()) {
int x = q.top().second; q.pop();
if(vis[x]) continue;
vis[x] = true;
for(int i = head[x]; i; i = edge[i].nxt) {
register int y = edge[i].to;
if(dst[y] > dst[x] + edge[i].val) {
dst[y] = dst[x] + edge[i].val;
q.push(make_pair(-dst[y], y));
}
}
}
return;
}
inline void work() {
for(int y = 1; y <= n; ++y) {
int x = pre[y], i = frm[y];
edge[i].val <<= 1; edge[i ^ 1].val <<= 1;
dij2();
ans = max(ans, dst[n]);
edge[i].val >>= 1; edge[i ^ 1].val >>= 1;
}
return;
}
int main() {
scanf("%d%d", &n, &m);
register int xx, yy;
register ll vv;
for(int i = 1; i <= m; ++i) {
scanf("%d%d%lld", &xx, &yy, &vv);
add(xx, yy, vv); add(yy, xx, vv);
}
dij();
work();
printf("%lld\n", ans - org);
return 0;
}