【题目背景】 很久很久以前 巨龙突然出现 带来灾难 带走啦公主又消失不见 【问题描述】 你在玩一个 RPG 类游戏,作为一名叫“达拉崩吧”的勇者,你需要打败巨龙来拯救公 主。 有一关中,有 n 座岛屿,m 座桥,每座桥连通两座岛屿,桥上会有一些敌人,玩家只 有消灭了桥上的敌人才能通过,与此同时桥上的敌人会对玩家造成一定伤害。 而且会有一个战斗力高达 9999999999(该数字与题目无关)的名叫“昆特牌提琴烤 蛋挞苏打马拉松”的巨龙镇守一座桥,以勇者目前的能力,是不可能通过的。 而巨龙是狡猾的,巨龙会镇守某一座桥,使得勇者受到最多的伤害才能从岛屿 1 到达 岛屿 n。当然,勇者会选择受到伤害最小的路径。 问,勇者要受到的伤害是多少。 【输入格式】 第一行两个整数 n; m。 接下来 m 行,每行三个整数 s; t; c,表示一座连接岛屿 s 和 t 的桥上的敌人会对勇者造 成 c 的伤害。 【输出格式】 一行,一个整数 d。d 表示勇者要受到的伤害是多少。 【样例输入】 3 4 1 2 1 1 2 2 2 3 1 2 3 2 【样例输出】 3 【数据范围】 100%的数据, 1 ≤ n ≤ 100000, 1 ≤ m ≤ 200000, 1 ≤ c ≤ 10000,数据保证任意删去 一条边后勇者可以从岛屿 1 到达岛屿 n
1-5:枚举删去哪一条边,跑一遍最短路。
6-8:跑出所有可能的路径,一一尝试一遍。
100%做法:
我们先从1为起点、从n为起点跑两边dij,获得每一个点到起点1、终点n的最短距离,其实距离和边权之间的关系相当于构建了由1为根的和由n为根的最短路树---所有最短路组成的树。
不难发现,要删除一条边,并使得最短路增大,一定要删除最短路上的边。所以我们找到从1到n的一条最短路链。找的方法就是在由n为根的最短路树上从1开始向N走。
接下来我们从这个最短路链上每一个点,在以1为根和以n为根的最短路树上进行bfs(仅向儿子bfs)。目的是找到对于每一个不在最短路链上的点x,找到1到x最短路与1到n最短路最后一个重合的点l[x],你也可以理解为在以1为根的最短路树上x与n的lca。同理还有以n为根的最短路上x和1的lca。
接下来我们枚举每一条不在最短路链上的边u->v,不难想到,从1到N经过边u->v的最短路一定是1->l[u]->u->v->r[v]->n的这种形式。那么在1->n的最短路上,l[u]->r[v]这一段区间内任意一条边的删除,从1到n的最短路有可能变为1->l[u]->u->v->r[v]->n。由于是最短路,所以就要更新所有这种形式的最小值。并且所有不在1->N最短路链上的边都能影响一个区间,所以这就变成了一个区间最小值问题,可以用线段树维护。用线段树维护1->N最短路上的边,线段树每一个元素代表删除这条边后最短路的长度。
最后我们扫一遍整个线段树,找最大值即可。
// user:halahen
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
const int maxm=500010;
int i,j,k;
int n,m,x,y,z,ans,anss=0;
int f1[maxn],f2[maxm],f3[maxm],f4[maxm],r,th;
int dis1[maxn],dis2[maxn],a[maxn],fa1[maxn],fa2[maxn];
int ll[maxn],rr[maxn];
int d1[maxm],d2[maxm],d3[maxm],d4[maxm],ha[maxn];
int read(){
int tot=0,fh=1;
char c=getchar();
while ((c<'0')||(c>'9')){ if(c=='-') fh=-1; c=getchar(); }
while ((c>='0')&&(c<='9')){ tot=tot*10+c-'0'; c=getchar(); }
return tot*fh;
}
struct SegmentTree{
int l[maxn*4],r[maxn*4],mi[maxn*4];
void build(int x,int ll,int rr){
int mid=(ll+rr)>>1;
l[x]=ll; r[x]=rr; mi[x]=1e9;
if (ll==rr) return;
build(x*2,ll,mid);
build(x*2+1,mid+1,rr);
}
void changge(int x,int ll,int rr,int w){
if ((ll<=l[x])&&(r[x]<=rr)){
mi[x]=min(mi[x],w);
return;
}
if ((r[x]<ll)||(rr<l[x])) return;
changge(x*2,ll,rr,w); changge(x*2+1,ll,rr,w);
}
void getans(int x,int w){
if (l[x]==r[x]){
if (ans<min(w,mi[x])){
ans=min(w,mi[x]); anss=1;
}
else{
if (ans==min(w,mi[x])) anss++;
}
return;
}
getans(x*2,min(w,mi[x]));
getans(x*2+1,min(w,mi[x]));
}
}tre;
void add(int x,int y,int w){
r++; f2[r]=y; f3[r]=w; f4[r]=f1[x]; f1[x]=r;
}
struct node{
int x,y,z;
node (int xx=0,int yy=0,int zz=0){ x=xx; y=yy; z=zz; }
}d[maxn];
bool operator < (node a,node b){ return (a.x>b.x); }
void dij(int *dis,int *fa,int S){
int i; node thi=node(0,S,0);
priority_queue<node> mp;
for (i=1;i<=n;i++) dis[i]=1e9;
mp.push(thi);
while (mp.size()!=0){
thi=mp.top(); mp.pop();
if (dis[thi.y]!=1e9) continue;
i=f1[thi.y]; dis[thi.y]=thi.x; fa[thi.y]=thi.z;
while (i!=0){
if (dis[f2[i]]==1e9) mp.push(node(thi.x+f3[i],f2[i],i));
i=f4[i];
}
}
}
void dfs(int x,int *l,int *fa){
int i=f1[x],faa;
ha[x]=1;
while (i!=0){
if (ha[f2[i]]==1){ i=f4[i]; continue; }
if (fa[f2[i]]==0){ i=f4[i]; continue; }
if (fa[f2[i]]%2==1) faa=f2[fa[f2[i]]+1];
else faa=f2[fa[f2[i]]-1];
if (faa==x){
if (l[f2[i]]==0) l[f2[i]]=l[x];
dfs(f2[i],l,fa);
}
i=f4[i];
}
}
int main(){
freopen("boss.in","r",stdin);
freopen("boss.out","w",stdout);
n=read(); m=read();
for (i=1;i<=m;i++){
x=read(); y=read(); z=read();
d1[i]=x; d2[i]=y; d3[i]=z;
add(x,y,z); add(y,x,z);
}
dij(dis1,fa1,1); dij(dis2,fa2,n);
r=1; x=n;
while (x!=1){
if (fa1[x]%2==1){
d4[(fa1[x]+1)/2]=1;
x=f2[fa1[x]+1];
}
else{
d4[fa1[x]/2]=1;
x=f2[fa1[x]-1];
}
r++;
}
x=n; ll[n]=r; rr[n]=r; th=r;
while (x!=1){
if (fa1[x]%2==1){
d4[(fa1[x]+1)/2]=1;
x=f2[fa1[x]+1];
}
else{
d4[fa1[x]/2]=1;
x=f2[fa1[x]-1];
}
r--; ll[x]=r; rr[x]=r;
}
tre.build(1,1,th-1);
memset(ha,0,sizeof(ha));
dfs(1,ll,fa1);
memset(ha,0,sizeof(ha));
dfs(n,rr,fa2);
for (i=1;i<=m;i++){
if (d4[i]==1) continue;
if (dis1[d1[i]]+d3[i]+dis2[d2[i]]>dis2[d1[i]]+d3[i]+dis1[d2[i]]) swap(d1[i],d2[i]);
tre.changge(1,ll[d1[i]],rr[d2[i]]-1,dis1[d1[i]]+d3[i]+dis2[d2[i]]);
}
tre.getans(1,1e9);
if (ans==dis1[n]){
printf("%d\n",ans);
return 0;
}
printf("%d\n",ans);
return 0;
}
/*
2 4
1 2 1
1 2 1
1 2 2
1 2 3
*/