题面传送门

题意:

给出一张 \(n\) 个点 \(m\) 条边的无向图 \(G\),第 \(i\) 条边连接 \(u_i,v_i\) 两个点,权值为 \(w_i\)。

你可以进行以下操作一次

  • 选择两条边 \(i,j(i<j)\),并令 \(w_i:=w_i+w_j\)。

求你可以得到的最短路的最大值。

\(n,m \in [1,3 \times 10^5]\)

很明显,你可以预处理出每条边的边权可以增加的最大值 \(add_i\)。

显然答案满足单调性,考虑二分答案。

需检查使得存在一条边 \(i\) 使得:

  • 所有 \(1\) 到 \(n\) 的长度小于 \(mid\) 的路径都经过这条边。
  • \(dis_{1,n}+add_i \geq mid\)。

检查第二个条件很好办,直接在原图上跑一遍最短路就可以了。

要检查第一个条件,可以将所有在至少一条 \(1\) 到 \(n\) 的长度小于 \(mid\) 的边全部拎出来建成一张新图 \(G'\)。

我们的目标就是找到 \(G'\) 中的一条边,把它割掉后 \(1\) 与 \(n\) 不连通。因为这样就不存在 \(1\) 到 \(n\) 的长度小于 \(mid\) 的路径。

可以使用 \(\texttt{tarjan}\) 找割边的方法找到这条边 \((u,v)\)。

但单纯地找割边也是不靠谱的,还需检查以下两个条件是否满足:

  1. 它在点 \(1\) 与点 \(n\) 所在的连通块内。
  2. \(1,n\) 不能全在点 \(u\) 或点 \(v\) 包含的连通块中。例如下图中 \((1,2)\) 就是反例:

怎样检查这两个条件?

第一个条件很好办,从 \(1\) 开始 dfs,把能访问到的点都访问了就行了。

第二个条件等价于检查点 \(v\) 能否通过某条不包含 \((u,v)\) 的路径到达 \(n\)。你记录一个数组 \(vis_x\) 表示 \(x\) 能否到达 \(n\)。然后你每次访问一个未访问过的点的时候就执行 \(vis_x|=vis_y\) 就行了。

最后,聊一聊这题我调 3h 的原因:1. 没有注意到上面的条件 \(2\),一直卡在 35 分(梦回 APIO?T2 调 2.5h 因为没考虑到某个条件) 2. 模板被错,if(low[y]>dfn[x]) 写成 if(low[y]>low[x])(说明模板最好考前敲一遍)。

/*
Contest: -
Problem: NFLSOJ 711
Author: tzc_wk
Time: 2020.10.19
*/
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define all(a) a.begin(),a.end()
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,0x3f,sizeof(a))
#define y1 y1010101010101
#define y0 y0101010101010
typedef pair<int,int> pii;
typedef long long ll;
int n,m,mx[300005];
int u[300005],v[300005],w[300005];
struct graph{
int hd[300005<<1],nxt[300005<<1],to[300005<<1],wei[300005<<1],id[300005<<1],ecnt=0;
inline void clear(){fill0(hd);fill0(to);fill0(wei);fill0(nxt);fill0(id);ecnt=0;}
inline void adde(int u,int v,int w,int _id){to[++ecnt]=v;wei[ecnt]=w;id[ecnt]=_id;nxt[ecnt]=hd[u];hd[u]=ecnt;}
} g,ng;
ll dis1[300005],disn[300005];
inline void dijkstra(){
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
memset(dis1,63,sizeof(dis1));memset(disn,63,sizeof(disn));
dis1[1]=disn[n]=0;q.push(make_pair(0,1));
while(!q.empty()){
pair<ll,int> p=q.top();q.pop();
ll sum=p.fi;int x=p.se;
if(dis1[x]<sum) continue;
for(int e=g.hd[x];e;e=g.nxt[e]){
int y=g.to[e],z=g.wei[e];
if(dis1[y]>dis1[x]+z){
dis1[y]=dis1[x]+z;
q.push(make_pair(dis1[y],y));
}
}
}
q.push(make_pair(0,n));
while(!q.empty()){
pair<ll,int> p=q.top();q.pop();
ll sum=p.fi;int x=p.se;
if(disn[x]<sum) continue;
for(int e=g.hd[x];e;e=g.nxt[e]){
int y=g.to[e],z=g.wei[e];
if(disn[y]>disn[x]+z){
disn[y]=disn[x]+z;
q.push(make_pair(disn[y],y));
}
}
}
// for(int i=1;i<=n;i++) printf("%lld ",dis1[i]);printf("\n");
// for(int i=1;i<=n;i++) printf("%lld ",disn[i]);printf("\n");
}
int dfn[300005],low[300005],tim=0;
bool vis[300005],is[300005];vector<int> bri;
inline void tarjan(int x,int f){
dfn[x]=low[x]=++tim;
for(int e=ng.hd[x];e;e=ng.nxt[e]){
int y=ng.to[e],z=ng.id[e];
if(!dfn[y]){
tarjan(y,x);low[x]=min(low[x],low[y]);vis[x]|=vis[y];
if(low[y]>dfn[x]) is[z]=1;
}
else if(y!=f) low[x]=min(low[x],dfn[y]);
}
if(x==n) vis[x]=1;
}
inline bool check(ll x){
ng.clear();
memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));
memset(vis,0,sizeof(vis));tim=0;memset(is,0,sizeof(is));
// for(int i=1;i<=m;i++) printf("%d\n",w[i]);
for(int i=1;i<=m;i++){
if(dis1[u[i]]+disn[v[i]]+w[i]<x||
disn[u[i]]+dis1[v[i]]+w[i]<x)
ng.adde(u[i],v[i],1,i),ng.adde(v[i],u[i],1,i);
}
tarjan(1,0);if(!vis[1]) return 0;
for(int i=1;i<=m;i++){
ll d=min(dis1[u[i]]+disn[v[i]]+w[i],disn[u[i]]+dis1[v[i]]+w[i]);
// if(is[i]) printf("%d %d %d %lld %lld\n",u[i],v[i],w[i],d+mx[i],d);
if(vis[u[i]]&&vis[v[i]]&&is[i]&&d+mx[i]>=x) return 1;
}
return 0;
}
signed main(){
// freopen("enlarge8.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u[i],&v[i],&w[i]);
g.adde(u[i],v[i],w[i],i);g.adde(v[i],u[i],w[i],i);
}
for(int i=m;i;i--) mx[i]=max(w[i+1],mx[i+1]);
dijkstra();ll L=dis1[n]+1,R=5e14,ans=dis1[n];
// check(10);
while(L<=R){
ll mid=(L+R)>>1;
// printf("%lld %d\n",mid,check(mid));
if(check(mid)) ans=mid,L=mid+1;
else R=mid-1;
}
printf("%lld\n",ans);
return 0;
}

【2020五校联考NOIP #7】道路扩建的更多相关文章

  1. 【2020五校联考NOIP #6】三格缩进

    题意: 给出 \(n\) 个数 \(a_1,a_2,\dots,a_n\),你要进行 \(m\) 次操作,每次操作有两种类型: \(1\ p\ x\):将 \(a_p\) 改为 \(x\). \(2\ ...

  2. 【2020五校联考NOIP #8】自闭

    题目传送门 题意: 有一个 \(n \times m\) 的矩阵,里面已经填好了 \(k\) 个非负整数. 问是否能在其它 \(n \times m-k\) 个格子里各填上一个非负整数,使得得到的矩阵 ...

  3. 【2020五校联考NOIP #8】狗

    题面传送门 原题题号:Codeforces 883D 题意: 有 \(n\) 个位置,每个位置上要么有一条狗,要么有一根骨头,要么啥都没有. 现在你要给每个狗指定一个方向(朝左或朝右). 朝左的狗可以 ...

  4. 【2020五校联考NOIP #4】今天的你依旧闪耀

    题面传送门 题意: 对于一个长度为 \(n\)(\(n\) 为偶数)的排列 \(p\),定义一次"变换"后得到的排列 \(p'\) 为: \(p'_i=\begin{cases}p ...

  5. 【2020五校联考NOIP #3】序列

    题面传送门 原题题号:Codeforces Gym 101821B 题意: 给出一个排列 \(p\),要你找出一个最长上升子序列(LIS)和一个最长下降子序列(LDS),满足它们没有公共元素.或告知无 ...

  6. 【2020五校联考NOIP #7】伟大的卫国战争

    题面传送门 题意: 数轴上有 \(n\) 个点,现在要在它们之间连 \(m\) 条边,第 \(i\) 条边连接 \(a_i,b_i\) 两个点. 现在你要钦定每条边连在数轴的上方还是下方,使得任意两条 ...

  7. 【2020五校联考NOIP #6】最佳观影

    题意: 给出一个 \(k \times k\) 的网格和 \(n\) 次操作.其中 \(k\) 为奇数. 每次操作给出一个数 \(m\).每次你要找出一个三元组 \((x,l,r)\) 使得: \(r ...

  8. 【2020五校联考NOIP #2】矩阵

    咕咕咕到现在~ 题面传送门 题意: 给出一个 \(n\times n\) 的矩阵 \(A\).要你求有多少个 \(n\times n\) 的矩阵 \(B\) 满足: 每一行都是 \(1\) 到 \(n ...

  9. 【NOIP2016提高A组五校联考1】道路规划

    题目 分析 我们考虑,当现在有一个合法的集合时,如何往里面增加一个点,使这个集合仍然合法. 假设现在有一个合法的集合, 那么当我们加入一个点,它的道路穿过来整个集合,那么 然后搞一遍最长下降子序列就可 ...

随机推荐

  1. Vue3学习(七)之 列表界面数据展示

    一.前言 昨晚可能是因为更新完文章后,导致过于兴奋睡不着(写代码确实太容易让人兴奋了),结果两点多才睡着,大东北果然还是太冷了. 不知道是不是因为膝盖和脚都是冰凉的,所以才导致很晚才能入睡? 刚眯了一 ...

  2. rocketmq优雅停机往事

    1 时间追溯到2018年12月的某一天夜晚,那天我正准备上线一个需求完就回家,刚点下发布按钮,告警就响起,我擦,难道回不了家了?看着报错量只有一两个,断定只是偶发,稳住不要慌. 把剩下的机器发完,又出 ...

  3. 81. 搜索旋转排序数组 II

    题目 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同. 在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋 ...

  4. AIApe问答机器人Scrum Meeting 5.3

    Scrum Meeting 6 日期:2021年5月3日 会议主要内容概述:汇报两日工作. 一.进度情况 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 李明昕 后端 与前端对 ...

  5. Go语言核心36讲(Go语言进阶技术十一)--学习笔记

    17 | go语句及其执行规则(下) 知识扩展 问题 1:怎样才能让主 goroutine 等待其他 goroutine? 我刚才说过,一旦主 goroutine 中的代码执行完毕,当前的 Go 程序 ...

  6. pku 2425 A Chess Game (SG)

    题意: 给一个由N个点组成的一张有向图,不存在环.点的编号是0~N-1. 然后给出M个棋子所在的位置(点的编号)[一个点上可同时有多个棋子]. 每人每次可移动M个棋子中的一个棋子一步,移动方向是有向边 ...

  7. shell 脚本二进制安装mysql

    以下脚本的手动安装连接:https://www.cnblogs.com/leihongnu/p/12581793.html [ #/bin/bash#脚本安装 mysql,上传安装包至 /rootcd ...

  8. SpringBoot整合reids之JSON序列化文件夹操作

    前言 最近在开发项目,用到了redis作为缓存,来提高系统访问速度和缓解系统压力,提高用户响应和访问速度,这里遇到几个问题做一下总结和整理 快速配置 SpringBoot整合redis有专门的场景启动 ...

  9. 关于docker中容器可以Ping通外网,真机无法Ping通容器的问题

    首先我们要知道整体的框架结构,docker是我们安装在centos7上的,而centos7是安装在vmware上.其中docker中还有若干容器运行. 整体框架图如下: 我们将它分为两部分,一部分是d ...

  10. 设计模式学习-使用go实现建造者模式

    建造者模式 定义 适用范围 与工厂模式的区别 优点 缺点 参考 建造者模式 定义 Builder 模式,中文翻译为建造者模式或者构建者模式,也有人叫它生成器模式. 建造者模式(Builder Patt ...