【2020五校联考NOIP #7】道路扩建
题面传送门
题意:
给出一张 \(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\) 与点 \(n\) 所在的连通块内。
- \(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】道路扩建的更多相关文章
- 【2020五校联考NOIP #6】三格缩进
题意: 给出 \(n\) 个数 \(a_1,a_2,\dots,a_n\),你要进行 \(m\) 次操作,每次操作有两种类型: \(1\ p\ x\):将 \(a_p\) 改为 \(x\). \(2\ ...
- 【2020五校联考NOIP #8】自闭
题目传送门 题意: 有一个 \(n \times m\) 的矩阵,里面已经填好了 \(k\) 个非负整数. 问是否能在其它 \(n \times m-k\) 个格子里各填上一个非负整数,使得得到的矩阵 ...
- 【2020五校联考NOIP #8】狗
题面传送门 原题题号:Codeforces 883D 题意: 有 \(n\) 个位置,每个位置上要么有一条狗,要么有一根骨头,要么啥都没有. 现在你要给每个狗指定一个方向(朝左或朝右). 朝左的狗可以 ...
- 【2020五校联考NOIP #4】今天的你依旧闪耀
题面传送门 题意: 对于一个长度为 \(n\)(\(n\) 为偶数)的排列 \(p\),定义一次"变换"后得到的排列 \(p'\) 为: \(p'_i=\begin{cases}p ...
- 【2020五校联考NOIP #3】序列
题面传送门 原题题号:Codeforces Gym 101821B 题意: 给出一个排列 \(p\),要你找出一个最长上升子序列(LIS)和一个最长下降子序列(LDS),满足它们没有公共元素.或告知无 ...
- 【2020五校联考NOIP #7】伟大的卫国战争
题面传送门 题意: 数轴上有 \(n\) 个点,现在要在它们之间连 \(m\) 条边,第 \(i\) 条边连接 \(a_i,b_i\) 两个点. 现在你要钦定每条边连在数轴的上方还是下方,使得任意两条 ...
- 【2020五校联考NOIP #6】最佳观影
题意: 给出一个 \(k \times k\) 的网格和 \(n\) 次操作.其中 \(k\) 为奇数. 每次操作给出一个数 \(m\).每次你要找出一个三元组 \((x,l,r)\) 使得: \(r ...
- 【2020五校联考NOIP #2】矩阵
咕咕咕到现在~ 题面传送门 题意: 给出一个 \(n\times n\) 的矩阵 \(A\).要你求有多少个 \(n\times n\) 的矩阵 \(B\) 满足: 每一行都是 \(1\) 到 \(n ...
- 【NOIP2016提高A组五校联考1】道路规划
题目 分析 我们考虑,当现在有一个合法的集合时,如何往里面增加一个点,使这个集合仍然合法. 假设现在有一个合法的集合, 那么当我们加入一个点,它的道路穿过来整个集合,那么 然后搞一遍最长下降子序列就可 ...
随机推荐
- 【UE4】虚幻引擎技术直播汇总(含中英文直播)
B站虚幻引擎官方账号 中文直播 [中文直播]第35期 | 使用GIS在UE中创造真实地球风貌 | Epic 周澄清 [中文直播]第34期 | 包教包会的Epic MegaGrants申请之道 | Ep ...
- 剑指offer:JZ12 矩阵中的路径
JZ12 矩阵中的路径 描述 请设计一个函数,用来判断在一个n乘m的矩阵中是否存在一条包含某长度为len的字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上, ...
- OO第三单元JML总结
目录 目录一.JML语言的理论基础二.应用工具链三.部署SMT Solver四.部署JMLUnitNG/JMLUnit五.三次作业分析第一次作业第二次作业第三次作业六.总结与心得体会 一.JML语言的 ...
- OO第三单元
OO第三单元 JML语言理论基础,应用工具链 JML语言基础 JML简介 定义: JML 是一种形式化的. 面向 JAVA 的行为接口规格语言 作用: 开展规格化设计.这样交给代码实现人员的将不是可能 ...
- 『学了就忘』Linux基础 — 5、使用VMware创建虚拟机
目录 1.在VMware中创建虚拟机 (1)点击[创建新的虚拟机]. (2)选择系统安装方式 (3)选择客户机操作系统 (4)自定义虚拟机的名称和安装位置. (5)指定系统硬盘容量 (6)完成创建 2 ...
- 栈的压入、弹出顺序 牛客网 剑指Offer
栈的压入.弹出顺序 牛客网 剑指Offer 题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是 ...
- cf 24 Game (观察+.. 想一想)
题意: 给一个数N,从1到N. 每次取两个数,三种操作:加.减.乘,运算完得一个数,把那俩数删了,把这个数加进去. 重复操作N-1次. 问是否可能得到24.若可以,输出每一步操作. 思路: 小于4,不 ...
- 关于Asp.net core配置信息读取的源码分析梳理
概述 我们都知道asp.net core配置信息的读取离不开IConfigurationSource和IConfigurationProvider这两个类,ConfigurationSource可以提 ...
- Git - git push origin master 报错的解决方法
亲测实用,转载保存,原文地址:https://blog.csdn.net/kangvcar/article/details/72773904 错误提示如下: [root@linux1 php]# gi ...
- LoadRunner12回放与录制
系统版本 本人的操作系统是win10 版本是loadrunner12. 开启loadrunner自带的机票预订服务器 找到loadrunner自带的机票预订测试服务器下图中点击启动 如下图所示代表启动 ...