BZOJ4400 TJOI2012桥(最短路+线段树)
首先找出任意一条1~n的最短路径。显然删除的边只有在该最短路上才会对最短路长度产生影响。
不会证明地给出一个找不到反例的结论:删除一条边后,新图中一定有一条1~n的最短路径上存在一条边x->y,满足在原图中1~x的最短路和y~n的最短路上该删除边均不是必经边。
另一个显然的结论是,原图中经过边x->y情况下的最短路一定可以描述为1->l->x->y->r->n,其中l和r是之前找出的最短路上的两个点。因为如果在到达x之前在最短路上反复横跳,不如直接走原最短路。后者同理。
由两个结论容易发现,要考虑原问题,只需要枚举一条边x->y,求出l为1->x的最短路和1->n的最短路最早分离点,及r为y->n和1->n最短路的最晚重合点,用该路径长度更新原最短路上l~r这段区间的边被删除后的答案即可。在最短路dag上随便dp一下,线段树或者并查集实现区间更新即可。
// luogu-judger-enable-o2
// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 100010
#define M 400010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,p[N],t,d[N],point[N],id[N],degree[N],pos[N],D[2][N],f[2][N],tree[N<<2],qwq,mx,cnt;
bool flag[N],tag[M];
struct data{int to,nxt,len;
}edge[M];
void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
struct data2
{
int x,d;
bool operator <(const data2&a) const
{
return d>a.d;
}
};
priority_queue<data2> q;
void dijkstra(int start)
{
while (!q.empty()) q.pop();
memset(d,60,sizeof(d));d[start]=0;
memset(flag,0,sizeof(flag));
q.push((data2){start,0});
for (;;)
{
while (!q.empty()&&flag[q.top().x]) q.pop();
if (q.empty()) break;
data2 x=q.top();q.pop();
flag[x.x]=1;
for (int i=p[x.x];i;i=edge[i].nxt)
if (x.d+edge[i].len<d[edge[i].to])
{
d[edge[i].to]=x.d+edge[i].len;
q.push((data2){edge[i].to,d[edge[i].to]});
}
}
}//求start到所有点的单源最短路
void topsort()
{
int head=0,tail=0;
for (int i=1;i<=n;i++)
for (int j=p[i];j;j=edge[j].nxt)
if (d[i]+edge[j].len==d[edge[j].to]) degree[edge[j].to]++;
for (int i=1;i<=n;i++) if (!degree[i]) id[++tail]=i;
while (tail<n)
{
int x=id[++head];
for (int i=p[x];i;i=edge[i].nxt)
if (d[x]+edge[i].len==d[edge[i].to])
{
degree[edge[i].to]--;
if (!degree[edge[i].to]) id[++tail]=edge[i].to;
}
}
}//按最短路DAG拓扑排序
void canarrive(int u)
{
memset(flag,0,sizeof(flag));flag[u]=1;
for (int i=n;i>=1;i--)
{
int x=id[i];
for (int j=p[x];j;j=edge[j].nxt)
if (d[x]+edge[j].len==d[edge[j].to])flag[x]|=flag[edge[j].to];
}
}//判断每个点是否能到终点
void dfs(int k)
{
point[qwq++]=k;
for (int i=p[k];i;i=edge[i].nxt)
if (d[k]+edge[i].len==d[edge[i].to]&&flag[edge[i].to])
{
tag[i+1>>1]=1;
dfs(edge[i].to);
break;
}
}//找出S到T的任意最短路
void getpos()
{
memset(pos,60,sizeof(pos));
for (int i=0;i<=qwq;i++) pos[point[i]]=i;
}//求出每个点在最短路链中的位置
void getfirst(int op)
{
memset(f[op],60,sizeof(f[op]));
for (int i=1;i<=n;i++) D[op][i]=d[i];
for (int i=1;i<=n;i++)
{
int x=id[i];if (pos[x]<=qwq) f[op][x]=min(f[op][x],pos[x]);
for (int j=p[x];j;j=edge[j].nxt)
if (d[x]+edge[j].len==d[edge[j].to]&&!tag[j+1>>1]) f[op][edge[j].to]=min(f[op][edge[j].to],f[op][x]);
}
}//求出到每个点的最短路最早从哪个点分离 顺便记最短路
void cover(int k,int l,int r,int x,int y,int p)
{
if (l==x&&r==y) {tree[k]=min(tree[k],p);return;}
int mid=l+r>>1;
if (y<=mid) cover(k<<1,l,mid,x,y,p);
else if (x>mid) cover(k<<1|1,mid+1,r,x,y,p);
else cover(k<<1,l,mid,x,mid,p),cover(k<<1|1,mid+1,r,mid+1,y,p);
}
void dfs_tree(int k,int l,int r)
{
tree[k]=min(tree[k],tree[k>>1]);
if (l==r)
{
if (tree[k]==mx) cnt++;
else if (tree[k]>mx) mx=tree[k],cnt=1;
return;
}
dfs_tree(k<<1,l,l+r>>1);
dfs_tree(k<<1|1,(l+r>>1)+1,r);
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read(),m=read();
for (int i=1;i<=m;i++)
{
int x=read(),y=read(),z=read();
addedge(x,y,z),addedge(y,x,z);
}
dijkstra(1);
topsort();
canarrive(n);
point[0]=1;dfs(1);qwq--;
getpos();
getfirst(0);
dijkstra(n);
topsort();
reverse(point,point+qwq+1);
getpos();
getfirst(1);
for (int i=1;i<=n;i++) f[1][i]=qwq-f[1][i];
memset(tree,60,sizeof(tree));
for (int i=1;i<=n;i++)
for (int j=p[i];j;j=edge[j].nxt)
if (!tag[j+1>>1])
{
int x=i,y=edge[j].to;
if (f[0][x]<f[1][y])
{
cover(1,1,qwq,f[0][x]+1,f[1][y],D[0][x]+edge[j].len+D[1][y]);
}
}
dfs_tree(1,1,qwq);
if (mx==d[1]) cout<<mx<<' '<<m<<endl;
else cout<<mx<<' '<<cnt<<endl;
return 0;
//NOTICE LONG LONG!!!!!
}
BZOJ4400 TJOI2012桥(最短路+线段树)的更多相关文章
- [TJOI2012]桥(最短路+线段树)
有n个岛屿, m座桥,每座桥连通两座岛屿,桥上会有一些敌人,玩家只有消灭了桥上的敌人才能通过,与此同时桥上的敌人会对玩家造成一定伤害.而且会有一个大Boss镇守一座桥,以玩家目前的能力,是不可能通过的 ...
- 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了题目给出的最短路,手工搞出一个最短路,发现对答案没什么影响 所以干脆转化为经典问题:每次询问删掉一条边后的最短路 如果删掉的是非最短路边,那 ...
随机推荐
- return语句——学习笔记
return,可以提前结束其所在函数. 函数内不写,会自动加上return. 非引用返回: 引用返回:a=3,b=3 注意事项: 两种修改字符串某一位置值的方式:
- jenkins发布程序触发shell调用python脚本刷新akamai cdn api
刷新cdn的流程:jenkins获取git中的代码,触发脚本推送到生产环境中(即cdn的源站) --> 触发脚本获取git工作目录的更新列表,将更新列表拼凑成带域名信息的url,写入到目录中 - ...
- spark sql插入表时的文件个数研究
spark sql执行insert overwrite table时,写到新表或者新分区的文件个数,有可能是200个,也有可能是任意个,为什么会有这种差别? 首先看一下spark sql执行inser ...
- 导出swagger2生成的文档
百度了好多篇用法,没法用.特此记录一下 一.下载项目 下载https://github.com/Swagger2Markup/spring-swagger2markup-demo下的项目,保存,注意文 ...
- canvas固定画布
canvas作为非常方便的HTML绘图工具在web端的应用是非常多了. 那么会碰到一个问题,开始绘图的时候,网页总是晃动. 怎么办呢?只需在获取鼠标(触点)移动坐标的时候,添加清除默认动作就可以了. ...
- Spring cloud微服务安全实战-5-1单点登录基本架
基于微服务架构,前后端分离实现SSO 前后端分离到底是个什么样的架构. 中间不是用Nginx而是用Node JS. node.js在服务端的页面渲染,这样搜索引擎爬虫 来爬的时候 爬的就是html页面 ...
- 算法习题---5.7丑数(Uva136)
一:题目 丑数是指不能被除了2,,5以外的素数整除的数.将丑数从小到大排序 ,,,,,,,,,,,.... 求第1500个丑数 (一)求解方法 对于任意丑数x,他的2x,3x,5x都是丑数. 二:代码 ...
- 使用Scanner
在上个步骤中,每次要发不同的数据都需要修改代码 可以使用Scanner读取控制台的输入,并发送到服务端,这样每次都可以发送不同的数据了. 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
- boost写的异步客户端样例代码修改为支持断开重连的代码
考虑到boost的工业级强度,因此就直接用了,代码的官方示例地址:https://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/examples/ ...
- 【物联网】UI设计
https://designshidai.com/7337.html https://designshidai.com/24908.html http://www.qianqian-ye.com/sm ...