数据范围很大,然而 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 ", ans - org); return 0; }