题目描述
Farmer John 热衷于散步,每天早上他都要从 1 号仓库走到 n 号仓库。 Farmer John 家的 n 个仓库被 m 条双向道路连通起来,每条道路有一个长度 w。而Farmer John 又不喜欢走路,所以他走的是从 1 号仓库到 n 号仓库的最短路。
但是 Farmer 的奶牛们总想搞点事情,他们计划着把 m 条道路的其中一条变成原来长度的 2 倍,使得 Farmer John 可能会多走一点路。
他们想知道,最多能让 Farmer John 多走多少路呢?
输入
第一行一个正整数 n,m,表示仓库个数和道路条数。
接下来 m 行,每行三个正整数,表示每条双向道路的连接的仓库和该双向道路的长度。
输出
输出只有一行,表示最多能让 Farmer John 每天早上多走多少路。
样例输入
复制样例数据
5 7
2 1 5
1 3 1
3 2 8
3 5 7
3 4 3
2 4 7
4 5 2
样例输出
2
因为如果要变动一条路使得主人公走远路的话,那么肯定是要变动他的最短路,由于图可能很复杂,变动最短路上的任意一条路都可能造成意想不到的效果,所以要把这条最短路上的每一条边都尝试改变一下,求得最大值。
而如果要回溯路径的话,就需要一个标记数组以及DFS,然后按照链式前向星的思路沿着原路(双向图允许这种操作)回去。
//#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
const int INF = 0x3f3f3f3f;
using namespace std;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll lldcin()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
///Untersee Boot IXD2(1942)
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
/**Last Remote**/
struct node
{
mutable ll next,to,value;
}nodes[50000];
ll heads[50000],dis[50000],cnt=0;
bool vis[50000];
ll path2[50000],path[50000];
void cons(ll from,ll to,ll v)
{
nodes[cnt]=node{heads[from],to,v};
heads[from]=cnt++;
}
struct info
{
ll current,status,cost;
};
bool operator<(info a,info b)
{
return a.cost>b.cost;
}
void dij(ll s,ll h)//优先队列优化的迪杰斯特拉
{
reset(vis,0);
reset(dis,0x3f3f3f);
priority_queue<info>pq;
pq.push(info{s,0,0});
dis[s]=0;
while(!pq.empty())
{
info cur=pq.top();
pq.pop();
if(vis[cur.current])
continue;
vis[cur.current]=1;
for(int i=heads[cur.current];i!=-1;i=nodes[i].next)
{
ll t=nodes[i].to;
if(dis[t]>dis[cur.current]+nodes[i].value)
{
//cout<<nodes[i].value<<endl;
dis[t]=dis[cur.current]+nodes[i].value;
pq.push(info{t,0,cur.cost+nodes[i].value});
path[t]=cur.current;
}
if(cur.status<h)
{
if(dis[t]>dis[cur.current]+2*nodes[i].value)
{
dis[t]=dis[cur.current]+2*nodes[i].value;
pq.push(info{t,cur.status+1,cur.cost+2*nodes[i].value});
path[t]=cur.current;
}
}
}
}
}
void show(ll e)//路径展示,校对用
{
ll from=path[e];
stack<ll>stk;
stk.push(e);
while(vis[from])
{
stk.push(from);
from=path[from];
}
while(stk.size())
{
cout<<stk.top()<<endl;
stk.pop();
}
}
ll ans=0;
void traceback(ll current,ll n)//回溯路径
{
for(int i=heads[current];i!=-1;i=nodes[i].next)
{
ll to=nodes[i].to;
if(to==path2[current])
{
nodes[i].value*=2;//暂时变更权值
dij(n,0);
ans=max(ans,dis[1]);
nodes[i].value/=2;
traceback(to,n);
}
}
}
int DETERMINATION()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
ll n,m;
cin>>n>>m;
reset(heads,-1);
for(int i=1;i<=m;i++)
{
ll tmp1,tmp2,tmp3;
cin>>tmp1>>tmp2>>tmp3;
cons(tmp1,tmp2,tmp3);
cons(tmp2,tmp1,tmp3);
}
dij(1,0);
memcpy(path2,path,sizeof(path));
ll fir=dis[n];
//show(n);
traceback(n,n);
cout<<ans-fir<<endl;
return 0;
}