[TJOI2012]桥(最短路+线段树)
有n个岛屿, m座桥,每座桥连通两座岛屿,桥上会有一些敌人,玩家只有消灭了桥上的敌人才能通过,与此同时桥上的敌人会对玩家造成一定伤害。而且会有一个大Boss镇守一座桥,以玩家目前的能力,是不可能通过的。而Boss是邪恶的, Boss会镇守某一座使得玩家受到最多的伤害才能从岛屿1到达岛屿n(当然玩家会选择伤害最小的路径)。问, Boss可能镇守岛屿有哪些。
Solution
我们可以先找出一条最短路,那么我们要删去一条边的话,肯定要从这条路中删。
那么接着考虑一条不在这条路径上的边能够产生的贡献。
看起来有点麻烦,我们可以对于每个不在最短路上的点求一个pre一个nex,大概是这个意思(不太好用文字表述)。
这里的pre是最靠右的,next是最靠左的、
那么这条边能够产生贡献的条件是pre到next中的某条边被删掉。此时的最短路可能为dis[1][x]+l+dis[x][n].。
所以我们要对所有情况取min,这时可以用线段树维护最短路链,区间取min。
Code
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define N 100002
#define mm make_pair
#define inf 0x3f3f3f3f
using namespace std;
queue<int>q;
int head[N],tot,n,m,dis[][N],pre[N],tr[N<<],la[N<<],ans1,ans2,tag[N],s_t[N],l[N],top,r[N];
bool vis[N],gan[N<<];
struct node{
int n,to,l;
}e[N<<];
inline void add(int u,int v,int l){
e[++tot].n=head[u];
e[tot].to=v;
e[tot].l=l;
head[u]=tot;
}
inline void dij(int s,int tag){
memset(dis[tag],0x3f,sizeof(dis[tag]));
memset(vis,,sizeof(vis));
priority_queue<pair<int,int> >q;
q.push(mm(,s));dis[tag][s]=;
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;vis[u]=;
for(int i=head[u];i;i=e[i].n){
int v=e[i].to;
if(dis[tag][v]>dis[tag][u]+e[i].l){
dis[tag][v]=dis[tag][u]+e[i].l;pre[v]=u;
q.push(mm(-dis[tag][v],v));
}
}
}
}
void BFS(int s,int *a,int ta){
q.push(s);a[s]=s;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=e[i].n)if(!a[e[i].to]&&!tag[e[i].to]){
if(dis[ta][e[i].to]!=dis[ta][u]+e[i].l)continue;
int v=e[i].to;a[v]=s;q.push(v);
}
}
}
inline void pushdown(int cnt){
if(la[cnt]<tr[cnt<<]){tr[cnt<<]=la[cnt];la[cnt<<]=la[cnt];}
if(la[cnt]<tr[cnt<<|]){tr[cnt<<|]=la[cnt];la[cnt<<|]=la[cnt];}
la[cnt]=inf;
}
void upd(int cnt,int l,int r,int L,int R,int x){
if(l>=L&&r<=R){
if(x<tr[cnt]){tr[cnt]=x;la[cnt]=x;}
return;
}
int mid=(l+r)>>;
if(la[cnt]!=inf)pushdown(cnt);
if(mid>=L)upd(cnt<<,l,mid,L,R,x);
if(mid<R)upd(cnt<<|,mid+,r,L,R,x);
tr[cnt]=max(tr[cnt<<],tr[cnt<<|]);
}
void dfs(int cnt,int l,int r){
if(l==r){
if(l!=){
if(tr[cnt]>ans1){ans1=tr[cnt];ans2=;}
else if(tr[cnt]==ans1)ans2++;
}
return;
}
int mid=(l+r)>>;
if(la[cnt]!=inf)pushdown(cnt);
dfs(cnt<<,l,mid);dfs(cnt<<|,mid+,r);
}
int main(){
scanf("%d%d",&n,&m);int u,v,w;tot=;
for(int i=;i<=m;++i){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);add(v,u,w);
}
dij(,);int s=n;while(s!=)s_t[++top]=s,tag[s]=top,s=pre[s];s_t[++top]=;tag[]=top;
dij(n,);
for(int i=;i<=n;++i)
for(int j=head[i];j;j=e[j].n){
int v=e[j].to;
if(dis[][i]+dis[][v]+e[j].l==dis[][n]&&tag[i]&&tag[v])gan[j]=gan[j^]=;
}
for(int i=;i<=top;++i)BFS(s_t[i],l,); //t->s
for(int i=top;i>=;--i)BFS(s_t[i],r,); //s->t
memset(tr,0x3f,sizeof(tr));memset(la,0x3f,sizeof(la));
for(int i=;i<=n;++i)
for(int j=head[i];j;j=e[j].n)if(!gan[j]&&tag[l[i]]>tag[r[e[j].to]]){
int v=e[j].to;
// cout<<tag[r[v]]+1<<" "<<tag[l[i]]<<" "<<dis[0][i]+e[j].l+dis[1][v]<<endl;
upd(,,top,tag[r[v]]+,tag[l[i]],dis[][i]+e[j].l+dis[][v]);
}
dfs(,,top);if(ans1==dis[][n])ans2=m;
cout<<ans1<<" "<<ans2<<endl;
return ;
}
[TJOI2012]桥(最短路+线段树)的更多相关文章
- BZOJ4400 TJOI2012桥(最短路+线段树)
首先找出任意一条1-n的最短路径.显然删除的边只有在该最短路上才会对最短路长度产生影响. 不会证明地给出一个找不到反例的结论:删除一条边后,新图中一定有一条1-n的最短路径上存在一条边x->y, ...
- HDU5669 Road 分层最短路+线段树建图
分析:(官方题解) 首先考虑暴力,显然可以直接每次O(n^2) 的连边,最后跑一次分层图最短路就行了. 然后我们考虑优化一下这个连边的过程 ,因为都是区间上的操作,所以能够很明显的想到利用线段树来维 ...
- [BZOJ4699]树上的最短路(最短路+线段树)
https://www.cnblogs.com/Gloid/p/10273902.html 这篇文章已经从头到尾讲的非常清楚了,几乎没有什么需要补充的内容. 首先$O(n\log^2 n)$的做法比较 ...
- BZOJ 2725: [Violet 6]故乡的梦 最短路+线段树
2725: [Violet 6]故乡的梦 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 678 Solved: 204[Submit][Status ...
- Wannafly挑战赛2_D Delete(拓扑序+最短路+线段树)
Wannafly挑战赛2_D Delete Problem : 给定一张n个点,m条边的带权有向无环图,同时给定起点S和终点T,一共有q个询问,每次询问删掉某个点和所有与它相连的边之后S到T的最短路, ...
- 【BZOJ】BZOJ3040 最短路 线段树优化Dijkstra
题目描述 N个点,M条边的有向图,求点1到点N的最短路(保证存在). 1<=N<=1000000,1<=M<=10000000 输入格式 第一行两个整数N.M,表示点数和边数. ...
- BZOJ3073 [Pa2011]Journeys[最短路—线段树优化建边]
新技能get✔. 线段树优化建边主要是针对一类连续区间和连续区间之间建边的题,建边非常的优秀.. 这题中,每次要求$[l1,r1]$每一点向$[l2,r2]$每一点建无向边,然后单元最短路. 暴力建边 ...
- Codeforces 1163F 最短路 + 线段树 (删边最短路)
题意:给你一张无向图,有若干次操作,每次操作会修改一条边的边权,每次修改后输出1到n的最短路.修改相互独立. 思路:我们先以起点和终点为根,找出最短路径树,现在有两种情况: 1:修改的边不是1到n的最 ...
- [HNOI2014] 道路堵塞 - 最短路,线段树
对不起对不起,辣鸡蒟蒻又来用核弹打蚊子了 完全ignore了题目给出的最短路,手工搞出一个最短路,发现对答案没什么影响 所以干脆转化为经典问题:每次询问删掉一条边后的最短路 如果删掉的是非最短路边,那 ...
随机推荐
- API接口TOKEN设计
首先需要知道API是什么? API(Application Programming Interface)即应用程序接口.你可以认为 API 是一个软件组件或是一个 Web 服务与外界进行的交互的接 ...
- Oracle 内存参数调优设置
Oracle 数据库系统中起到调节作用的参数叫初始化参数,数据库管理员根据实际情况需要适当调整这些 初始化参数以优化Oracle系统. 1 主要系统参数调优介绍 2 系统内存参数的分配 2.1 Ora ...
- Highgo 瀚高数据库的简单搭建以及处理参数等.
1. 获取一个瀚高数据库的安装文件 我这边只获取了 瀚高的 2.0.4 的windows x64 版本的. 来源: 同事从供应商那里获取的. 2. windows上面简单安装 很简单 exe 一路ne ...
- Java8 Lambda和Stream的用法
package com.zhangxueliang.demo; import java.util.ArrayList; import java.util.List; import java.util. ...
- 建议1---理解Pythonic的概念
对于Pythonic的概念,众人都有自己的看法,但大家心中都认同一个更具体的指南,即Tim Peters的<The Zen of Python>.在这一篇充满禅意的诗篇中,有几点非常深入人 ...
- python之路--递归, 二分法
一 . 递归 自己调用自己, 递归的入口(参数) 和 出口(return), 树形结构的遍历. def func(): print("我是递归") func() func() ...
- python学习笔记(4)-基本数据类型-数字类型及操作
大学mooc 北京理工大学 python语言程序设计课程学习笔记 一.整数类型 可正可负,没有取值范围的限制(这个与c不同,c要考虑数据类型的存储空间).如pow(x,y),计算x的y次方,pow(2 ...
- MySQL系列:索引基本操作(4)
1. 索引简介 索引是一种特殊的数据库结构,可以用来快速查询数据中的特定记录. MySQL中索引包括:普通索引.唯一性索引.全文索引.单列索引.多列索引和空间索引等. 1.1 索引定义 索引由数据库表 ...
- Delphi之TStrings和TStringLists类
Delphi之TStrings和TStringLists类 有些类不是组件,但它们支持存在的组件.这些类是其他组件的典型属性,直接由TPersistent派生,如TStrings.TCanvas和TC ...
- 转载 -- CSS3 中关于 select 下拉列表的样式
截图效果: