题面传送门

题意:

给出一张 \(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. 使用寄存器点亮LED——2

    1. 项目:使用stm32寄存器点亮LED, 分别点亮红.绿.蓝3个灯. 2. 步骤 先新建个文件夹保存项目 再新建项目 将startup_stm32f10x_hd.s拷贝到该文件夹下 新建main. ...

  2. 编程题:X星人的金币

    X星人的金币 时问限制:3000MS 内存限制:589824KB 题目描述: X是人在一艘海底沉船上发现了很多很多很多金币.可爱的X星人决定用这些金币来玩一个填格子的游戏.其规则如下:第1个格子放2枚 ...

  3. CentOS 文本编辑器

    目录 1.Nano 1.1.基础命令 1.2.快捷操作 1.3.配置文件 2.Vim 2.1.四大模式 2.2.基础命令 2.3.标准操作 2.4.高级操作 2.5.配置文件 Linux 终端的文本编 ...

  4. str数组

  5. js实现日期格式化封装-八种格式

    封装一个momentTime.js文件,包含8种格式. 需要传两个参数: 时间戳:stamp 格式化的类型:type, 日期补零的方法用到es6语法中的padStart(length,'字符'): 第 ...

  6. 第36篇-return字节码指令

    方法返回的字节码相关指令如下表所示. 0xac ireturn 从当前方法返回int 0xad lreturn 从当前方法返回long 0xae freturn 从当前方法返回float 0xaf d ...

  7. NOIP模拟92(多校25)

    前言 所以说这次是 HZOI 多校联测巅峰????(题目,数据过水??) T1 石子合并 解题思路 签到题. 发现我们可以给每个数字附一个正负号,每个数字的贡献就是它本身乘上这个符号. 发现至少应该有 ...

  8. ONVIF客户端中预置位设置代码实现过程

    simpleOnvif的功能:提供支持Windows.Linux.arm.Android.iOS等各种平台的SDK库,方便集成,二次开发 之前跟大家分享了我们安徽思蔷信息科技的simpleOnvif的 ...

  9. springcloud优雅停止上下线与熔断

    SpringCloud 服务优雅上下线 Spring Boot 框架使用"约定大于配置"的特性,优雅流畅的开发过程,应用部署启动方式也很优雅.但是我们通常使用的停止应用的方式是 k ...

  10. CentOS服务器的网络配置与部署

    1.系统安装与软件安装 1.1选择CentOs7.9release版本用作所研发系统部署服务器,官网以及所选择镜像为地址为:http://ftp.sjtu.edu.cn/centos/7.9.2009 ...