【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】道路规划
题目 分析 我们考虑,当现在有一个合法的集合时,如何往里面增加一个点,使这个集合仍然合法. 假设现在有一个合法的集合, 那么当我们加入一个点,它的道路穿过来整个集合,那么 然后搞一遍最长下降子序列就可 ...
随机推荐
- javascript-vue介绍
vue.js是一个用于创建web交互页面的库 从技术角度讲,vue专注于MVVM模型的viewModel层,它通过双向数据绑定把view层和model层连接起来,实际DOM封装和输出格式都被抽象为Di ...
- 【c++ Prime 学习笔记】第7章 类
类的基本思想是数据抽象和封装 数据分离抽象是一种依赖于接口和实现分离的编程/设计技术.接口包括用户能执行的操作,实现包括类的数据成员.接口实现的函数体.定义类所需的各种私有函数 封装实现了类的接口和实 ...
- cs224n 2019
视频链接 相关资源 Notes 笔记下载 笔记2 需要挂梯子,不然不显示图片,如果用ssr,要调到全局模式 转自:bitJoy CS224N(1.8)introduction and Word Vec ...
- NOIP模拟83(多校16)
前言 CSP之后第一次模拟赛,感觉考的一般. 不得不吐槽多校联测 OJ 上的评测机是真的慢... T1 树上的数 解题思路 感觉自己思维有些固化了,一看题目就感觉是线段树. 考完之后才想起来这玩意直接 ...
- SpringBoot加密配置属性
一.背景 在系统中的运行过程中,存在很多的配置属性,比如: 数据库配置.阿里云配置 等等,这些配置有些属性是比较敏感的,是不应直接以明文的方式出现在配置文件中,因此对于这些配置我们就需要加密来处理. ...
- 一套比较好用的公众号UI框架-weui
最近工作原因 需要在pd端弄一套js类似bootstrap框架 由于使用环境是在公众号终端用的比较多! 类似上面这样的样式 所以我从微信官方开始找起 最后找到了WEUI 还别说 真的挺好用的 这是大佬 ...
- 简单易懂讲IO
流式 IO 是传统 IO,通过构造输入输出流,讲信息从一个地方读取,输出到另一个地方.常见的有读取文件以及写入文件. 基本 API 流失 IO 基本可以分为两个门派,一个以 InputStream 和 ...
- linux job
通常运行的进程 ctrl-z之后会暂停到后台 bash test.sh Linux-4.15.0-36-generic-x86_64-with-Ubuntu-16.04-xenial #39~16.0 ...
- pycharm基本使用python的注释语法
pychram基本使用 1.主题选择 file settings Editor color Scheme 2.pycharm切换解释器 file settings Project Python Int ...
- Centos 7 端口聚合
简单粗暴,直接复制命令就好了 还是先啰嗦一下,添加网卡之后,如果没有网卡配置文件,可以通过nmcli con show 先查看网卡的唯一ID,然后复制其他的网卡配置文件,修改device项,name项 ...